Where a feature sits

Four rolled numbers build the entire face layout. They say not only where eyes, nose and mouth sit, but also how much room each of them has.

A feature does not sit in pixels here but in spherical coordinates of the head: u is longitude – 0 at the centre of the nose, ±1.48 at the ear – and v is latitude, +1.57 at the crown, −1.57 at the chin. Those are the same two numbers out of which the head shape builds its surface. How a feature gets from there into the picture is in the next chapter (Space); this one is about who hands out the addresses.

Four genes

macheLayout draws four numbers and derives everything else from them:

GeneRangeOutliers up toWhat it means
augeU0.30 … 0.800.20 … 0.90half the eye spacing in longitude
mitte−0.36 … 0.14−0.55 … 0.28centre of the face field. Low means: large forehead
spreizung0.62 … 1.100.50 … 1.30how far apart eyes, nose and mouth lie vertically
skala0.78 … 1.300.66 … 1.55size factor for all facial features

The range is the rule, the outlier the exception: eight draws in ten land inside the range, exactly where rng.range would put them. Only the outermost tenth on each side is stretched and reaches the outlier bound – eyes almost at the bridge of the nose or almost at the ear, a face in the lower third of the skull, features that fill the head. How that works is explained under Randomness. A sheet on which every head were extreme would be monotonous again.

They come from a forked stream: macheLayout(strom(seed, 'layout')). That is not cosmetic. If the layout lay in the main stream it would have to be drawn there before the feature choice – the features depend on the position, after all. Every later change to the layout, even a single new rng.range call, would then shift the features of all seeds. But a seed is the address of a face.

What a zone is

A zone is the room a feature has on the head: centre and half-measures in spherical coordinates. That is exactly what a frame in a drawing means – whoever fills it bumps into nothing.

Two properties carry the whole construction. The zones tile: no gap, no overlap. And the centre of a zone is not necessarily the anchor of the feature that sits in it – the face centre from the gene mitte lies somewhere other than the nose anchor, which is the centre of its own zone.

Without zones the layout only sets anchors, and the size comes from an independent factor. Then a long nose runs through the mouth whenever the anchors stand close together – and nobody can say which of the two numbers was wrong.

The nose zone is the interesting case: it is root and bridge in one. It begins at eye level above and ends at the mouth zone below. That it still does not overlap the eye zones is down to its width: it is only as wide as the bridge of the nose and runs between the eyes.

The cheek zone

The sixth zone carries nothing built – only colour on the skin: rosy strokes, the red dot, freckles. It still belongs in the layout, because it is the wall the mouth runs into. The mouth zone ends where the cheek begins; half the mouth width is therefore no longer a fixed number but follows from the eye spacing (via the cheek anchor) and from the eye size (via the reserve the cheek keeps for its own strokes).

Before, half the mouth width stood in the layout as 0.62, and the cheeks worked out their anchor by themselves. Together that meant: with close-set eyes a wide grin ran into the cheek strokes, and nobody could say which of the two numbers was wrong.

The wall does not hold absolutely, though. A lachen runs across almost the whole face – and then the cheek gets out of the way: first upwards, towards the eye, then outwards. Outwards alone would take it to the ear, where the surface tips away and five strokes become one. This is worked out in the image, along the mouth's transverse axis (wangenFeld), not in spherical coordinates: the mouth is drawn flat, the cheek sits on the sphere.

The constants

ConstantValueWhy exactly this
AUGENZONE0.34 Share of the distance eye line ↔ mouth line. Reaches past the eye line, the bridge of the nose sits there too
MUNDZONE0.5 Not smaller: at 0.2 a drawn row of teeth turned into a black blot
BRUECKE0.45 Share of half the eye spacing for the bridge of the nose. The rest is eye width – which is why close-set eyes stay small without anyone clamping them separately
WANGE1.35 How far the eye zone reaches outwards. The ear sits at 1.48
BACKE_AUSSEN0.22 How far outside the eye the cheek sits, capped at 0.9 – further out the surface tips away
BACKE_HALB0.16 × eye scale What the cheek keeps for its strokes, clamped to 0.1…0.19. Measured against the eye, because the style works the cheeks out from the eye size – a fixed reserve would take a fifth of the mouth width from a small-eyed face for strokes it never draws that wide
half the mouth width0.23…0.8 No longer a constant: cheek anchor − cheek reserve. Together with MUNDZONE the proportion of every mouth

The zone is the ceiling, not the measure

The zone says where a feature may not go. It does not say how large it is. That is the distinction the first version of this edition failed on.

The zone taken as the measure

The eyes are two percent of the head width – pinheads, barely recognisable as eyes.

Cause: the zone height was taken directly as the eye size. But the eye zone is flat: between brow and bridge of the nose there is little room, and that room is the limit the eye must not bump into – not its size.

Fix: a desired measure from the face scale, capped by the zone, and with a lower bound below which no feature can fall.

You can see the construction in each of the four lines: a Math.min of desire and zone measure, wrapped in a klemm. And the caps are loose – hoehe * 4.5 for the eye, hoehe * 1.9 for the mouth height. A crowded face gets smaller features, but no needles.

Small features in a large head are a baby

The sheet looks like a nursery: all the heads seem young, soft and alike, no matter how different their skulls are.

Cause: the eye size hung hard off the zone height. Where the zones lay narrow the features became tiny – and tiny features in a large head are the baby schema. But the sheet is supposed to show people, not babies.

Fix: lower bounds for eye, nose and mouth, and a skala range that is more open at the top than before. Features drawn large are adults.

Squashed twice

Features shrink as soon as the head turns. Zones sitting low become a line.

Cause: every feature is drawn in a local system that hangs off its anchor – the function f.to(lx, ly) converts a coordinate from −1…1 into a picture point. In doing so it squashes both axes with the foreshortening factors fx and fy of the surface at that spot. So whoever measures the zone dimensions in picture pixels – which are already foreshortened – and feeds them in squashes them a second time.

Fix: platz() computes both axes foreshortened back, each with its own factor. What comes out is a measure in the local system – exactly what to() expects. Where fx and fy come from is in the chapter Space.

Position and catalogue

Out of the genes fall three named steps: augenAbstand (close · normal · wide), gesichtsLage (low · middle · high) and gesichtsGroesse (small · normal · large). They are strings and not numbers, for a single reason: they are the hook for conditions in the catalogue.

The catalogue holds the variants as data – weights, plus conditions. Two of them depend on the position: nurBei is hard, the variant drops out; lieber is soft, its weight triples. The third depends on a feature already drawn instead of on the position: nichtMit.

RuleExampleWhy
nurBei weit, ring, offen only with normal or wide eye spacing Large eye shapes need room between the anchors, otherwise they overlap at the bridge of the nose
lieber punkt and strich preferably with close spacing Small shapes packed together are the strongest caricature
nurBei grinsen, zaehne, offen only with a normal or large face A row of teeth in a crowded mouth is a black blot
nichtMit kappe, stirnband, kopfhoerer not over a mass of hair They lie on the skin; over a shell they push a bulge out at the hairline
nichtMit augenringe not next to rosy cheeks Two statements in the same place read as a rash
nichtMit wangenbogen only with eyes that have an eyeball (WANGENBOGEN_AUGEN) A line or a cross has no lower edge for a cheek to cover

nichtMit looks at what was already drawn earlier in macheDna – the headwear comes after the hairdo, the mark after eye and cheeks. That makes the draw order a contract in two respects: it keeps the streams stable, and it ensures a condition only ever looks backwards.

The shortcut would have been shorter: draw anything and set the incompatible combination to keine afterwards. That is exactly what stood here, and it was a silent lie – the weight of the struck variant fell off the table instead of being redistributed onto the permitted ones. Hats over hairdos were a quarter rarer than the catalogue said because of it.

The last line is the most important: if nurBei makes everything drop out, the unfiltered list wins. A category may never be empty – a head without eyes is not a head but a crash.

A single re-roll reads the condition in both directions

While a DNA is being built, looking backwards is enough: what has not been drawn yet cannot interfere. In the workshop the situation is a different one – there a single feature is re-rolled, and everything around it has already been drawn.

The cap drops out of the table when the hair is a mass. The other way round nothing was ever written, because the hair comes before the cap. Re-roll the hair while a cap sits on the head and you would get a spiky cut under the cap – a combination that appears on no sheet, because the draw never produces it.

sperreFuer therefore reads the same rule twice: once forwards (what does the candidate rule out?) and once backwards (who rules IT out?). It returns the category that is responsible – which lets the workshop say "a bun does not allow that" instead of disabling a button without a word.

The price is a restriction one can see: under a hair mass there is no cap any more – not even when the cap is exactly what one wanted to roll. That is more honest than a combination which does not exist on the sheet.