Regular polygon plates stacked vertically, each rotated a fraction of a turn, with hidden lines removed.
One turn, spread over the stack
Each level of the tower is the same polygon, rotated by a fraction of a step:
float startAngle = i * 2f * MathF.PI / (steps * n);
steps is the polygon’s vertex count and n the number of levels, so across the
whole stack the rotation adds up to 2π / steps — exactly one vertex’s worth. The top
of the tower is the bottom rotated by one facet, which means the twist closes on
itself and the tower reads as continuous rather than as a stack that ran out.
For a square at fifty levels that is 90° / 50 — under two degrees per level, and the
twist is only legible because there are fifty of them.
The top few levels. Each is a polygon flattened vertically by a factor of 0.4,
which is the whole of the isometric projection — there is no camera and no matrix.
Ruled sides
A level is not a solid. It is a ring of points, and the side wall is the ruled
surface between consecutive rings: for each point on this ring, a quadrilateral to
the corresponding point on the next.
The code picks out only the points on the silhouette — those on the far side of the
leftmost and rightmost extremes — so the walls that would be hidden inside the tower
are never generated at all:
if ((pt.Y >= mostLeft.Y && pt.X <= 0f) ||
(pt.Y >= mostRight.Y && pt.X >= 0f))
sidePts.Add(pt);
That is back-face culling, done by comparing coordinates rather than by computing
normals, and it works because the projection is fixed and axis-aligned.
A third of the stack.
Hidden-line removal, not painting
The levels accumulate into a PolygonList, and each new polygon is clipped against
everything already in it before being drawn. Nothing is painted over: a line that
would be hidden is shortened or removed rather than covered.
That distinction matters for a piece drawn as strokes rather than fills. Painting over
requires an opaque fill, which would make the drawing solid; clipping leaves it as
line work that a plotter could produce, and every visible segment is a real segment.
It also fixes the drawing order. Top-down is not a preference here — it is a
requirement, because the clipping is one-directional and a level must be added before
anything it should occlude.
Half.
Three quarters. The silhouette edges are continuous across levels because consecutive
rings differ by less than two degrees.
The whole tower.
Tone from bale size
The fill of each level is not a colour but a bale — a count of hatch lines chosen
so that tone steps evenly in perceived density:
result[k] = (int)MathF.Round(MathF.Log(target) / logBase);
The count is the solution of 1 − (1 − 1/n)^k = target: how many independent marks at
rate 1/n are needed to reach a given coverage. It is the same saturating curve that
ink follows on paper, inverted, so that a linear ramp of targets produces a linear
ramp of apparent tone.
Variants
| Rendering | Levels | Polygon | Spacing | Sides | Ink |
|---|
| Pink Tower Spiral | 50 | square | 2.5 | yes | #FF1493 on black |
| Orange Tower Hex | 40 | hexagon | 3.0 | yes | #FF6600 on #0a0a0a |
| Purple Tower Triangle | 60 | triangle | 2.0 | yes | #BF00FF on #0d0d0d |
| Crimson Tower Pentagon | 45 | pentagon | 2.7 | yes | #DC143C on #040000 |
| Teal Tower Octagon | 35 | octagon | 3.5 | yes | #00E5FF on #000a0a |
| Amber Hex Stack | 72 | hexagon | 1.8 | no | #FFB300 on #080500 |
The polygon decides how much the tower twists in total — one facet: 120° for a
triangle, 90° for a square, 72° for a pentagon, 60° for a hexagon, and 45° for an
octagon. Fewer sides means a wider, more dramatic twist; the octagon is nearly a
smooth cylinder while the triangle is unmistakably a screw. The Amber Hex Stack omits
the side panels entirely, rendering only the ring at each level, which gives a dense
layered texture rather than a tower body.
Determinism
Nothing is seeded and nothing is random. Every ring is a closed-form function of its
index, the culling is a coordinate comparison, and the clipping is exact polygon
arithmetic in a fixed order.