Isometric cubes that spawn half-size cubes at their own corners, until the splitting rule runs out of nerve.
A hexagon is a cube
The primitive is a regular hexagon split into three rhombi meeting at the centre:
new Rhombus(Up, UpRight, Center, UpLeft),
new Rhombus(Center, UpRight, DownRight, Down),
new Rhombus(Center, Down, DownLeft, UpLeft),
The vertices are named by where they sit — Up is straight above the centre and
the rest follow clockwise in 60° steps — so each face reads as a shape rather than
as a handful of indices.
Three rhombi at sixty degrees are the isometric projection of a cube — the oldest
optical illusion in tiling, and the reason the drawing reads as solid geometry rather
than as flat hexagons.
The Positive flag chooses between two triples of rhombi, which is the same cube seen
from above or from below. Both are the same hexagon; only the internal edges move, and
the eye flips the cube accordingly.
The first cube, at 140 units. Everything in the finished piece descends from it.
Splitting, with decreasing confidence
foreach (var spawn in hex.GetSpawnPoints())
if (spawn.Depth < MaxDepth &&
(rng.NextDouble() < SplitChance / (1 + spawn.Depth * 0.05) || spawn.Depth < 2))
pool.Enqueue(spawn);
Two clauses, and they do different jobs.
spawn.Depth < 2 forces the first two levels: whatever the coin says, every cube down
to depth two splits. That guarantees the composition has a structure rather than
occasionally being a single cube.
Beyond that the chance is SplitChance / (1 + depth × 0.05) — 0.8 at depth two,
falling to about 0.70 at depth six. A gentle decay, and the consequence is that the
tree thins gradually rather than terminating: at every depth most cubes still split,
and the ones that do not leave gaps at every scale.
Depth one. Children are spawned at the parent’s corners at half the radius.
Depth two, the last guaranteed level.
Depth four. Some branches have stopped and some have not, and there is no pattern to
which — that is the coin.
Breadth-first, and why it matters
The generator uses a queue, not a stack:
var pool = new Queue<Hexagon>();
…
var hex = pool.Dequeue();
hexagons.Add(hex);
So the list comes out in depth order: every cube at depth d before any cube at
depth d+1. Two things follow.
The drawing order is depth order, and each cube is filled with the background colour
before being stroked — so a smaller, later cube paints over the larger one it sits on.
The occlusion that makes the piece read as stacked geometry is entirely
drawing-order, and reversing the traversal to depth-first would produce a different
image from the same set of cubes.
It also means the stages above can withhold deep cubes without disturbing anything:
the arrangement is generated in full at every stage, so the coins land the same way
and the cubes already drawn are exactly the ones in the finished piece.
All six levels.
Six renderings
| Rendering | Seed | Treatment |
|---|
| Cyber Cyan | 12345 | cyan strokes on pure black — the baseline |
| Hot Pink | 23456 | pink on near-black, one generation deeper |
| Carved Jade | 45678 | faces fill with three jade tints, so the cubes read as solids |
| Violet Glow | 56789 | a wide translucent halo stroked under every edge |
| Fading Ember | 67890 | strokes fade toward the background as depth grows |
| Paper Ink | 15196 | ink on paper, a sparse growth centred inside the frame |
Four of the six go beyond new ink: they change what is drawn, not just what it
is drawn with.
carved-jade fills each face with one of three jade tints — lightest on the
face that reads as the top — so the cubes are flat-shaded solids and the
occlusion happens between volumes rather than outlines. violet-glow strokes
the whole set once more, first, with a wide translucent halo; everything drawn
afterwards — the background-coloured fills in particular — occludes it the way
a cube occludes the edge behind it. fading-ember fades every stroke toward
the background as its depth grows, so the small cubes recede and the lattice
reads as a single cooling object.
paper-ink inverts the ground — ink strokes on warm paper — and shrinks the
growth to fit the frame: a smaller first cube, a lower split chance, and a seed
whose branches spread evenly. It is the one rendering that opts into
CenterGrowth: after generation the set’s ink is measured and shifted so its
bounding box sits centred on the canvas. Branches lean whichever way the coin
took them, so centring is a measurement, not a promise about the seed. The
others overflow the frame on purpose.
Each rendering has its own seed, so the six are independent growths of the same
rule.
The museum plate
The bundle’s gallery opens with the piece as it would hang: the Cyber Cyan
growth, framed. MuseumFrame is a presentation layer that wraps any square
piece — a gallery wall, a bottom-weighted window mat, a thin frame with a
hairline profile, and a soft shadow — and draws the artwork unchanged through
a clip, scaled into the mat window. The frame knows nothing about how the
artwork is generated; it calls the piece’s own Draw inside the window, so the
same treatment could hang anything.
There is one framed plate, not a framed copy of every variant. Framing is a
presentation mode: the gallery shows how the piece hangs, the variants show how
it was rendered, and the two layers stay apart.
Determinism
One Random is created per generation, seeded from the preset, and consumed once per
spawn point in breadth-first order. The generator is System.Random, which the
project’s determinism policy flags as not guaranteed stable across .NET versions.