Fallen, die schon zugeschnappt sind

Jeder Eintrag hier ist einmal passiert. Das Symptom war jedes Mal sichtbar und die Ursache jedes Mal woanders, als man zuerst gesucht hat – deshalb steht die Sammlung an einem Ort.

Ein Generator hat eine unangenehme Eigenschaft: er scheitert nicht mit einer Ausnahme, sondern mit einem Bild. Nichts stürzt ab, nichts wird rot, es sieht nur falsch aus – und zwar oft nur bei einem von hundert Seeds oder in einer von zwanzig Drehungen. Wer solche Fehler sucht, sucht meistens an der Stelle, an der er das Symptom sieht, und findet sie an einer Stelle drei Schritte davor.

Die Muster wiederholen sich. Ein Sprung in einer Randfunktion ist immer ein Loch in der Fläche, die daraus gebaut wird. Ein Wurf nach einer Sichtbarkeitsprüfung ist immer ein Flackern. Und alles, was an einem Index statt an einem Winkel hängt, springt bei der nächsten Drehung.

Vorzeichen und Richtungen

Der Schmollmund

Symptom: Jedes Lächeln ist ein Schmollmund. Und zwar so überzeugend, dass man lange in der Kurve nach dem Fehler sucht.

Ursache: Die y-Achse eines Ankers zeigt nach OBEN – sie folgt dem Breitengrad zum Scheitel. Die y-Achse des Canvas zeigt nach UNTEN.

Lösung: Jede Formfunktion in gesicht.ts rechnet in Canvas-Richtung und dreht das Vorzeichen in ihrem eigenen to um. Nicht zentral, sondern in jeder Funktion – weil jede ihren eigenen Maßstab mitbringt und der Wechsel dort steht, wo man ihn beim Lesen der Kurve braucht.

Das Dach unter dem Auge

Symptom: Die Augenringe sahen aus wie ein zweites Lid: Scheitel am Auge, Enden hängend. Lange niemandem aufgefallen, weil sie blass sind.

Ursache: Der Bogen lief von 1.15π bis 1.85π um eine Mitte unter dem Auge – das ist die obere Hälfte eines Kreises, ein Dach. Ein Ring unter dem Auge folgt aber dem unteren Lid: eine Schale, Enden nach oben.

Lösung: Untere Kreishälfte (0.15π bis 0.85π) um eine Mitte knapp unter dem Auge. Dieselbe Falle wie der Schmollmund, nur im Winkel statt im Vorzeichen.

Die eingestülpte Wange

Symptom: Ohren werden in die Wange hinein gezeichnet statt daneben; auf der abgewandten Seite erscheinen Merkmale, die dort nichts zu suchen haben.

Ursache: Die Flächennormale wurde zur Kamera hin geflippt. Dann besteht auch die abgewandte Seite den nz-Sichtbarkeitstest, und der lift entlang der Normale zeigt in die falsche Richtung.

Lösung: Die Normale zeigt auswärts vom Kopfzentrum, nie zum Betrachter. Damit heißt nz < 0 ehrlich „von der Kamera abgewandt". Siehe Raum.

Das Ohr als abgefallener Henkel

Symptom: Zwischen Ohr und Kopf klafft eine Lücke; das Ohr schwebt daneben.

Ursache: Der Ohrbogen wurde bündig an der Haut angesetzt. Die gezeichnete Kontur ist aber eine geglättete Silhouette und liegt ein Stück innerhalb des Punktes, an dem das Ohr sitzt.

Lösung: Die Fläche des Ohrs greift weiter in den Kopf hinein als sein Strich – ein Saum hinter der Wurzel.

Das angebissene Ohr

Symptom: Beim gedrehten Kopf schrumpft das zugewandte Ohr zur Sichel am Rand, und die Kontur läuft quer hindurch.

Ursache: Beide Ohren lagen unter der Kopffläche. Für das abgewandte stimmt das; das zugewandte wandert mit der Drehung hinter die Silhouette und liegt dann vor der Wange.

Lösung: Eigene Ebene zugewandtes-ohr hinter der Kopffläche, und welches Ohr dort landet, sagt seine Normale – nicht seine Seite im Bild. Der Bogen läuft dabei um den Einzug über die Kontur auf die Wange, ohne Linie am Ansatz. Siehe Merkmale.

Der Hals neben dem Kinn

Symptom: Dreht der Kopf, wandert der Hals seitlich weg und wird dabei schmaler.

Ursache: Er hing an zwei Ankern auf der Oberfläche. Ein Ellipsoid hat in jeder Drehung nahezu denselben Umriss – nur die Punkte darauf laufen darunter weg. Die sichtbare Kinnkante bleibt also fast stehen, der Oberflächenpunkt nicht.

Lösung: Der Hals hängt am Umriss, dort wo der Kopf im Bild wirklich endet. Breite und Kragen kommen dagegen aus dem ungedrehten Kopf: ein Körper wird nicht schmaler, wenn der Kopf sich dreht, und ein Hemd nickt nicht mit.

Die Nase radiert das vordere Auge weg

Symptom: Bei gedrehtem Kopf fehlt ein Stück des nahen Auges.

Ursache: Die Nase wurde vor beiden Augen gezeichnet. Sie hat Volumen und stellt sich frei – sie soll das ferne Auge verdecken, aber nicht das nahe.

Lösung: Die Reihenfolge lautet fernes Auge → Nase → nahes Auge; welches vorn ist, entscheidet die z-Tiefe der beiden Anker. Dasselbe gilt für den Bart: er liegt unter der Nase, also wird er vor ihr gezeichnet. Siehe Das Blatt.

Ränder und Flächen

Die Quetschung

Symptom: Ein Wulst rund um den Schädel, in der Silhouette auf beiden Seiten dieselbe Kante auf derselben Höhe – und zwar in jeder Drehung.

Ursache: Die Beule (beule) hing nur an der Höhe. Eine nur höhenabhängige Welle multipliziert x und z gleichmäßig; das ist kein Buckel, sondern ein Ring.

Lösung: Ein cos(u)-Anteil in der Welle. Dann sitzt die Beule an einer Stelle der Oberfläche. Siehe Kopfform.

Der Exponent auf sin und cos

Symptom: Bei starker Kastigkeit reißen Lücken in die Silhouette, und die Anker verhalten sich nicht mehr wie erwartet.

Ursache: Ein Exponent auf sin/cos hat am Äquator unendliche Steigung. Die Abtastung kommt nicht mit, und die Tangenten-Referenz, an der jeder Anker sein lokales System aufhängt, ist verzerrt.

Lösung: Die Superellipse als glatte radiale Beule an den Diagonalen annähern, über sin(2u) und sin(2v). Nirgends unendlich steil.

Die Delle in der Wange

Symptom: Am breitesten Punkt des Kopfes sitzt eine tiefe, weich verlaufende Einbuchtung.

Ursache: Ein leeres Winkelfach im Umriss. Am breitesten Punkt springt das projizierte y zwischen benachbarten Ringen um mehr als eine Fachbreite – dort bleibt ein Fach leer. Die anschließende Glättung verschmiert die Null zu einer Delle.

Lösung: Leere Fächer werden überbrückt, bevor geglättet wird. Die Reihenfolge ist der ganze Punkt. Siehe Punktwolke.

Der Lappen quer über das Gesicht

Symptom: Ab einer bestimmten Drehung legt sich eine Haarfläche quer über das Gesicht.

Ursache: Der Umriss der Frisur nahm auch ihre Rückseite mit. Die hängt bei einer Schale mit tiefer Unterkante bis unter die Kopfmitte; rutscht sie in die unteren Winkelfächer, hat der Bogen „rundum Masse" und schließt sich zum Ring.

Lösung: UmrissOpt.hinter – ein Punkt zählt nur, wenn er zu sehen ist. Die Schwelle liegt bei rz < −0.15 und nicht bei 0: an der Silhouette selbst liegt die Schale um null, und ihr äußerster Punkt im Fach darf ein Stück dahinter sitzen.

Der Faden an der Schläfe

Symptom: Ein dünner Strich läuft von der Frisur über die Wange nach unten, ohne Fläche daneben.

Ursache: Zwei Quellen, die sich verfehlen. Die Ansatzlinie endete weiter außen als der Umriss; das Polygon schloss sich über eine Sehne, die Füllung hörte dort auf, und der gezeichnete Ansatz lief daneben weiter. In einer früheren Fassung kam dasselbe Symptom aus zu wenigen Längengraden in der Schalenwolke – dann hatte der schmale Lappen an der Schläfe Lücken in den Winkelfächern.

Lösung: stutzeAnsatz wirft weg, was jenseits des Umrisses liegt, und die Schale wird mit 144 Längengraden abgetastet statt mit 56.

Das Loch in der Füllung

Symptom: Ein schmaler Keil fällt aus der Frisur heraus und kreuzt ihren Außenrand.

Ursache: Die Klemme des Haaransatzes sprang stufig, und zwar um mehr als den Abstand zweier Abtastpunkte. Zwischen den beiden Punkten stürzte die Randlinie ab.

Lösung: Weich statt in Stufen (t·t·(3−2t)). Das ist der allgemeine Fall: ein Sprung in einer Randfunktion ist immer ein Loch in der Fläche, die daraus gebaut wird.

Der waagerechte Keil – und das nasse Haar

Symptom A: An der Unterkante der Frisur ragt seitlich ein waagerechter Keil aus dem Kopf. Symptom B: Die Frisur ist an den Seiten platt und klebt am Schädel.

Ursache: Zwei Fehler dicht beieinander. Läuft die Schalendicke gar nicht aus, steht sie an der Unterkante in voller Dicke und wird radial nach außen sichtbar (A). Läuft sie über die ganze Höhe aus, bleibt oben nichts übrig (B).

Lösung: Nur das letzte Stück über dem Ansatz wird dünner; der Rest steht in voller Dicke, auch an der Schläfe.

Die gekappte Zunge und der Schnitt in Augenhöhe

Symptom: Die Frisur endet an der Schläfe mit einem geraden waagerechten Schnitt, oder ihre Spitze hakt ins Gesicht zurück.

Ursache: Umriss und Ansatz kommen aus verschiedenen Quellen und hören nicht am selben Punkt auf. Wer die Naht am engsten Punkt schneidet, trifft irgendeine Stelle auf der schmalen Zunge und kappt ihre Spitze – dort liegen die beiden Ränder die ganze Strecke dicht beieinander.

Lösung: An der spätesten engen Stelle schneiden, auf beiden Seiten. Und den verbleibenden Rest nicht mit einer Sehne schließen, sondern mit einem Bogen, der die Richtung des Außenrands fortsetzt (rundeZipfel). Siehe Haar und Hut.

Die Perlenkette und die Säge

Symptom: Locken sehen aus wie Perlen auf einer Schnur – oder wie eine Säge.

Ursache: Perlen entstehen, wenn Ballen auf eine glatte Kante gelegt werden: der Rand läuft darunter durch, und das Auge liest Linie-Kreis-Muster. Die Säge entsteht, wenn die Ausbuchtungen Sinusbögen sind – die laufen an beiden Enden flach aus und treffen den Nachbarn in einer Spitze.

Lösung: Der Rand selbst wird zur Folge von Wickeln, und die Ausbuchtung ist ein Halbkreis: er steht an seinen Enden senkrecht, jeder Wickel wird eine runde Beule mit einer Kerbe daneben.

Drei Wellen statt zwei Bögen

Symptom: Die Oberkante des Herzens auf dem Mund war bei kleiner Kerbe kein runder Bogen, sondern eine Reihe aus drei Buckeln.

Ursache: Gipfel und Flanken standen als feste Punkte in der Liste, und nur der Mittelpunkt hing am Regler. Bei kleiner Kerbe stand die Mitte höher als ihre eigenen Flanken.

Lösung: Eine Form, die ein Regler verändert, nicht aus Gipfeln und Tälern zusammensetzen, sondern als eine Grundform plus eine Störung rechnen: hier ein Bogen und eine Glocke, die in ihn einschneidet. Siehe Merkmale.

Maße und Größen

Die Zone als Maß

Symptom: Augen von zwei Prozent Kopfbreite.

Ursache: Die Zonenhöhe wurde direkt als Größe genommen. Die Augenzone ist aber flach – zwischen Braue und Nasenwurzel ist wenig Platz –, und ihre Höhe ist nicht die Größe des Auges, sondern die Grenze, an die es nicht stoßen darf.

Lösung: Wunschmaß aus der Gesichtsskala, gedeckelt durch die Zone, mit einer Untergrenze. Die Zone ist die Obergrenze, nicht die Vorgabe. Siehe Zonen.

Kleine Züge in einem großen Kopf

Symptom: Ein Blatt voller Babys.

Ursache: Kleine Züge in einem großen Kopf sind das Kindchenschema. Die erste Fassung band die Augengröße hart an die Zonenhöhe; ein gedrängtes Gesicht bekam Stecknadeln.

Lösung: Untergrenzen für Auge, Nase und Mund. Und derselbe Gedanke eine Ebene höher: Ohne genug Spanne in der Kopfform sind alle Köpfe Eier – und Eier sind Babys.

Doppelt gestaucht

Symptom: Merkmale schrumpfen bei gedrehtem Kopf, tief sitzende Zonen werden zum Strich.

Ursache: Die Zonengröße wurde in Pixeln gemessen und dann an f.to() übergeben – das staucht lx mit fx und ly mit fy noch einmal.

Lösung: platz() rechnet beide Achsen verkürzt zurück, bevor sie als Maß herausgehen.

Der Hut in der Luft

Symptom: Bei dicker Frisur steht das Haar über der Krone, und der Hut hängt daneben.

Ursache: Der Hut maß den blanken Schädel. Was er umschließen muss, ist aber der Schädel plus das Haar darauf.

Lösung: haarPolster – beim Afro als Kreisschnitt der Kugel auf der Sitzhöhe, sonst als gleichmäßiger Aufschlag. Verwandt: das Hutband saß auf dem Kronenfuß, also genau unter dem Krempenansatz, und las sich als Schatten unter dem Hut. Es sitzt jetzt höher an der Krone.

Der Pilz und die verschwundene Krempe

Symptom: Hüte, die entweder Pilze sind oder zwischen den Ohren verschwinden.

Ursache: Kronenhöhe und Krempenbreite wurden einzeln gewürfelt. Hohe Krone mit weiter Krempe ist ein Pilz, flache Krone mit knapper Krempe ist unsichtbar – und gleichverteilte Werte landen ohnehin alle in der Mitte.

Lösung: Nicht die Achsen würfeln, sondern die Sorte: Fedora, Trilby, Sonnenhut, Zylinder, Eimer. Derselbe Gedanke trägt die Afro-Sorten und die zwei Größenklassen der Locken.

Ein Blatt in neun Maßstäben

Symptom: Eine Frisur läuft in die Nachbarzelle – oder, nach dem naheliegenden Gegenmittel, steht jeder Kopf in einer anderen Größe.

Ursache: Eine Frisur mit eigener Form (der Afro) kann breiter sein als der Kopf hoch ist. Wer den Platzbedarf nicht kennt, hat nur schlechte Möglichkeiten.

Lösung: Der Stil meldet an, was er braucht (Raumbedarf); reicht es nicht, wird nicht dieser eine Kopf kleiner, sondern das ganze Blatt. Neun Maßstäbe sehen aus wie ein Fehler, ein etwas kleineres Blatt sieht nach Absicht aus.

Zufall und Ströme

Die verschobene DNA

Symptom: Nach einer harmlosen Änderung sind alle Gesichter andere Leute.

Ursache: Ein neues Feld wurde mitten in die Zieh-Reihenfolge von macheDna eingeschoben. Ab dieser Stelle bekommt jede folgende Ziehung eine andere Zahl.

Lösung: Neue Felder immer ans Ende anhängen. Wo das nicht geht, einen eigenen Strom forken (strom(seed, 'layout')). Dieselbe Regel gilt eine Ebene tiefer für die Streuung im Stil: neue Werte hinter die bestehenden Züge. Siehe Zufall.

Das flimmernde Gesicht

Symptom: Bei jedem Lidschlag ändert das ganze Gesicht seine Strichführung.

Ursache: Der Verzug kam aus einem laufenden Zufallsstrom. Ein einziger übersprungener Zug – ein geschlossenes Auge zeichnet weniger Linien – verschiebt alle folgenden Ziehungen.

Lösung: Der Verzug hängt an einer Spur, also an einem Namen. Gleicher Name plus gleicher Seed ergibt in jedem Bild dasselbe Zittern, unabhängig davon, was vorher gezeichnet wurde. Siehe Der Stift.

Das flackernde Muster

Symptom: Bei jeder kleinen Drehung ändern alle Kringel im Afro ihre Größe.

Ursache: Die Würfe fielen nach der Sichtbarkeitsprüfung. Ein Kringel, der sich gerade wegdreht, zieht dann den ganzen Strom hinter sich her.

Lösung: Erst alle Würfe, dann prüfen, was sichtbar ist. Allgemein: keine Ziehung darf von einer Bedingung abhängen, die sich pro Bild ändert.

Der springende Zierrat

Symptom: Stacheln, Fransen und Locken springen bei jedem Atemzug um eine Position weiter.

Ursache: Sie hingen an Indizes des Außenrands. Der Rand ist eine Abtastung der Silhouette und wandert mit jeder kleinen Drehung um einen Punkt.

Lösung: An festen Winkeln um die Kopfmitte aufhängen (randZuWinkeln). Dann steht der Zierrat still und gleitet nur mit der Silhouette. Dasselbe gilt für die Rauung des Afro-Randes.

Der Wackelkontakt und das Fernsehrauschen

Symptom: Das Blatt zappelt.

Ursache: Zwei Varianten desselben Fehlers. Würfelt jede Farbfläche ihr Fehlregister einzeln, rutscht jede woandershin – das ist kein Druck, das ist ein Wackelkontakt. Und wird das Papierkorn je Bild neu gewürfelt, ist es kein Papier mehr, sondern Rauschen (abgesehen davon, dass ein paar tausend Punkte je Bild teurer wären als der ganze Rest).

Lösung: Das Register hängt am Seed, also am Kopf – eine Richtung für das ganze Gesicht. Das Korn wird einmal in eine Kachel gezeichnet und danach als Muster gefüllt.

Bewegung

Der kochende Punkt

Symptom: Die Pupillen zittern.

Ursache: Der Punkt kochte mit dem Takt mit. Bei einer Linie liest sich das als Stift, bei einem Punkt als Zittern – eine Pupille, die je Takt woanders sitzt, ist keine Handzeichnung, sondern ein Fehler.

Lösung: punkt() kocht nie; sein Verzug hängt nur am Seed. Dasselbe gilt für kleine blasse Nebenlinien (ruhig): Augenringe und Schraffuren, die mitkochen, lesen sich als Flackern des Bildes.

Das Zittern kurzer Linien

Symptom: Kurze Züge – Mund, Braue – werden von Bild zu Bild sichtbar länger und kürzer.

Ursache: Die gleichmäßige Abtastung traf den Endpunkt nur bis auf Rundung. Ob der letzte Schritt gerade noch passt oder gerade nicht mehr, kippt mit jeder winzigen Längenänderung.

Lösung: Der Endpunkt gehört immer dazu. Verwandt: der Verzug skaliert mit der Zuglänge, und kurze Züge kochen kaum – derselbe Betrag ist auf einer langen Kontur ein Schlingern und auf einer kurzen Braue ein Sprung des ganzen Strichs.

Der Kamm und der Topf

Symptom: Neun Köpfe bewegen sich wie ein Kamm, und ihre Linien setzen alle im selben Moment neu an.

Ursache: Gleiche Federsteifigkeit für alle, und ein Takt, der aus einer gemeinsamen Uhr ohne Versatz kommt.

Lösung: Jeder Kopf bekommt seine eigene Steifigkeit, seine eigene Atemphase und einen eigenen taktVersatz – alle drei aus dem Seed. Auch das Umherschauen ohne Zeiger läuft auf zwei Sinus mit unrunden Perioden, sonst nickt die ganze Reihe im Takt.

Die aufgemalte Brille

Symptom: Die Gläser sehen aufgemalt aus statt davorzustehen.

Ursache: Sie waren über den Anker gezeichnet und schmiegten sich damit der Wölbung an – sie verkürzten wie Haut.

Lösung: Die Brille ist eine Figur im Kopfraum: zwei Kreise in der Frontalebene, ein Steg, zwei Bügel zum Ohr, gedreht und projiziert wie der Schädel selbst. Ein gedrehter Kopf verkürzt ein Glas dann nur um den Kosinus der Drehung – und genau das tut ein Glas. Siehe Raum.

Fallen, die kein Bild zeigt

Alle bisherigen Fallen haben ein Symptom: man sieht sie am Kopf. Die vier hier haben keines. Sie bauen fehlerfrei, sie werfen nichts, die Konsole bleibt still – und trotzdem stimmt etwas nicht. Deshalb steht hinter jeder inzwischen ein Wächter statt eines Kommentars.

Die Kopie, die auseinanderläuft

Symptom: Derselbe Seed zeigt in der Doku einen anderen Kopf als auf dem Blatt – andere Augengrößen, ein anderer Stern im Auge. Kein Fehler, nur ein Unterschied.

Ursache: Die Schritt-für-Schritt-Tafel führte die Zeichenreihenfolge als Nachbau, samt nachgestellter Zufallszüge. Als der Kern von der Hex-Gabelung auf benannte Ströme umgestellt wurde, zog der Nachbau weiter über die alte. Der Kommentar darüber sagte „muss mitgepflegt werden" – das ist kein Mechanismus, das ist eine Hoffnung.

Lösung: Die Tafel fragt den Stil nach seinen Zügen, statt sie nachzubauen. Was eine Demo zeigen will, muss sie sich holen können; kann sie es nicht, fehlt ein Export. Siehe Reihenfolge.

Das übersetzte Attribut

Symptom: Die Marke über dem Blatt steht als Miniatur da, ohne ihre schwarzen Kästen. Der Compiler ist zufrieden, die Konsole leer.

Ursache: Ein Umbenennungslauf hatte Bezeichner übersetzt und dabei auch Zeichenketten erwischt: aus font-size wurde font-mass, aus width="…" ein breite="…". Ein SVG übergeht ein Attribut, das es nicht kennt, kommentarlos – es beschwert sich nicht, es zeichnet nur anders.

Lösung: check-vokabular.mjs kennt eine Liste von Formen, die es nur als Schaden geben kann: eine CSS- oder SVG-Eigenschaft mit einer deutschen Hälfte.

Die Brücke, die zwei war

Symptom: Keines. Genau das ist die Falle.

Ursache: Im Stilblatt, im Kommentar über der Bildschleife und in dieser Doku stand übereinstimmend, die einzige Rolle, die ans Canvas geht, sei --marke-canvas. Die App las längst auch --flaeche. Gemerkt hat es niemand, weil an dieser Grenze nichts kaputtgeht: getPropertyValue auf einen Namen, den es nicht gibt, gibt einen leeren String zurück.

Lösung: Die Brücke ist eine namentliche Liste in check-rollen.mjs. Siehe die zweite Grenze.

Der Pfad, der die falsche Seite liefert

Symptom: /docs zeigt das Blatt statt dieser Doku – mit Status 200, ohne Umleitung, ohne Meldung.

Ursache: Ohne Schrägstrich am Ende ist /docs für den Entwicklungsserver kein Ordner, sondern ein unbekannter Pfad, und ein unbekannter Pfad bekommt die Anwendung. Ein 404 wäre ein Hinweis gewesen; ein 200 mit der falschen Seite ist keiner.

Lösung: Eine 301 auf /docs/, in Entwicklungs- und Vorschauserver gleichermaßen – ein Unterschied zwischen beiden wäre dieselbe Falle noch einmal.

Was daraus folgt

Die meisten dieser Fehler waren keine Denkfehler, sondern Fehler in der Reihenfolge: erst glätten, dann Lücken füllen; erst prüfen, dann würfeln; erst messen, dann stauchen. In einem Generator ist die Reihenfolge Teil der Korrektheit, und sie steht in keiner Signatur.

Deshalb tragen viele Stellen im Code einen Kommentar, der nicht sagt, was dort passiert, sondern was passiert, wenn man es anders macht. Wer diese Sammlung gelesen hat, weiß, warum.

Und wo ein Kommentar nicht reicht, steht ein Wächter. Der Unterschied ist keine Feinheit: ein Kommentar wird gelesen, wenn jemand an der richtigen Stelle nachsieht, ein Wächter meldet sich von allein. Die vier Fallen oben haben das gemeinsam – alle vier standen als Verabredung aufgeschrieben, und alle vier sind trotzdem passiert.