Was macht handdrawn-3d?
Du modellierst das Motiv in 3D mit wenigen einfachen Volumenkörpern, und das Kit zeichnet es per Hand. Flächen erhalten drei flache Marker-Töne von einer Lichtquelle oben links. Benachbarte Flächen mit demselben Ton verschmelzen zu einer einzigen Waschung. Die Silhouette wird schwer und die Falten heller mit wackeligen, sich verjüngenden Linien auf cremefarbenem Papier. Die Szene wird pro Frame einmal gezeichnet, wobei t einen Loop durchläuft. Die Ausgabe ist eine animierte SVG-Schleife: Die Frames werden per CSS umgeschaltet, ohne Skript, sodass sie in Browsern und <img>-Tags abspielbar ist. Text verwendet eine integrierte handgezeichnete Schriftart mit vollständiger Vietnamesisch-Unterstützung.
Kit: assets/kit.js · Renderer: assets/render.mjs · alle Funktionen und Optionen: references/kit.md (vor dem Schreiben einer Szene lesen) · ausgearbeitete Beispiele: examples/ (Tasse, Teekanne, Toaster, Windmühle: das passendste lesen).
Einrichtung (einmalig)
Für PNG/GIF-Export wird @resvg/resvg-js benötigt. Wenn render.mjs angibt, dass es fehlt, führe npm install im Ordner dieses Skills aus. Das SVG selbst benötigt nichts.
Vor dem Zeichnen
- Ist es zeichenbar? Wenn das Motiv abstrakt ist („Hoffnung“, „Produktivität“), zeichne nichts Vages. Schlage eine oder zwei konkrete Szenen vor, die es zeigen, und zeichne dann die Szene, die der Benutzer auswählt.
- Diagramme, Diagramme, UI, Schaltflächen, interaktive Dinge: nicht dieses Skill.
- Was bewegt sich? Jedes Bild animiert das Objekt selbst: die Kamera bewegt sich nie. Wähle eine oder zwei Bewegungen, die zum Motiv gehören. Ein Kesseldeckel klappert und dampft. Toast springt hoch. Die Flügel einer Windmühle drehen sich. Ein Ventilator dreht sich. Der Schwanz einer Katze wedelt. Eine Lampe nickt. Eine Pflanze wiegt sich. Wenn der Benutzer eine Bewegung nennt, nimm diese. Wenn sich nichts plausibel bewegen kann, verwende Dampf, ein sanftes Wippen oder Wiegen, und das Eigenzittern der Linien.
Arbeitsablauf
- Teile. Liste die echten Teile des Motivs auf und erkläre, wie jedes aus Volumenkörpern aufgebaut ist. Schreibe es als Tabelle in einem Kommentar am Anfang der Szene: Teil · Aufruf · Größe/Position · Farbe. Modelliere nach den echten Teilen (Ränder, Deckel, Knöpfe, Griffe, Füße, Schlitze, Scharniere), nicht nach einem Klumpen mit Namen darauf. Suche Proportionen nach, wenn du unsicher bist.
- Modelliere es in
scene.js(Welt: x rechts, y hinten, z oben, Boden z = 0; mm-ähnliche Einheiten; Rahmung ist automatisch):- runde Dinge, die du auf einer Töpferscheibe drehen könntest →
k.lathe(Behälter erhaltenwall:),k.cylinder,k.sphere - kastenförmige Dinge →
k.box(round:für weiche Geräteecken), ungewöhnliche Konturen →k.extrude - Griffe, Ausgüsse, Rohre, Beine, Kabel, Stiele →
k.tube, beginnend innerhalb des Körpers (wird an der Oberfläche abgeschnitten) - Inhalt eines Behälters →
{ in: container }; flache Zeichen auf einer Fläche →k.panel/k.linemit{ on: solid } - Drehe das gesamte Motiv mit
k.group({ rotate: { z: 45 } }, …), wenn seine „Seitenansicht“ dem Betrachter zugewandt sein soll (ein Teekannenausguss links und der Griff rechts)
- runde Dinge, die du auf einer Töpferscheibe drehen könntest →
- Animiere mit
t∈ [0, 1): sich bewegende Teile kommen in einek.group({ about, rotate, at }, …), gesteuert vonk.wave(),k.pulse()oder360 * t. Jede Bewegung muss an ihren Ausgangspunkt beit = 1zurückkehren. - Rendern und betrachten:
Öffnenode <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png --strip --thumbout/scene.png(ein Standbild) undout/scene-frames.png(6 Frames über den Loop) mit dem Lesewerkzeug und sieh sie dir an. Füge--gridhinzu, um Gitterkoordinaten abzulesen. Überprüfeout/scene-128.png: Es muss bei 128 px noch als Motiv erkennbar sein. - Korrigieren und neu rendern. Überprüfe:
- Ist es auf den ersten Blick als Motiv erkennbar? Zuerst die Silhouette.
- Nichts in der falschen Reihenfolge gezeichnet: ein Teil, das durch einen Körper scheint, ein fernes Teil über einem nahen, verdeckter oder durchstechender Inhalt. Korrigiere es mit den Regeln unter Wie Volumenkörper angeordnet werden in
references/kit.md: getrennte Volumenkörper,in:,on:, nur das modellieren, was aus einer Öffnung herausragt, undlayerals letztes Mittel. - Teile berühren das, was sie hält. Nichts schwebt, es sei denn, es soll (ein hüpfender Deckel).
- Die Bewegung ist im Frame-Streifen erkennbar und loopt ohne Sprung.
- Beschriftungen sitzen in den Rändern und kreuzen die Zeichnung nur so wenig wie nötig.
Wiederhole 4–5, bis es richtig ist (normalerweise 2–4 Runden). Rendere die endgültige Version ohne
--grid.
Nie ausliefern, ohne das Standbild und den Frame-Streifen betrachtet zu haben. Liefere den SVG-Pfad (das animierte Bild) sowie das PNG und zeige das PNG. Füge --gif out/scene.gif hinzu, wenn der Benutzer ein GIF wünscht oder das SVG an einem Ort abgespielt werden muss, der keine SVG-Animation unterstützt (Chat-Apps, einige E-Mail-Clients).
Stilregeln
- Ein Look: Tinte + flache Marker-Töne auf Papier. Keine Verläufe, Glühen, Weichzeichner, Deckkraft-Tricks, SVG-
<text>oder rohes SVG. Nur das Kit verwenden. - Farbe: Palettennamen (siehe
references/kit.md), 3–5 pro Bild plus Tinte. Palettennamen sehen am besten aus; jedes Hex wird abgemildert. Hell, Mitte und Dunkel kommen automatisch von jeder Füllung. Schattiere nicht mit zusätzlichen Volumenkörpern. - Kamera: isometrisch standardmäßig. Ändere
sheet.cameranur aus einem Grund. Eine niedrigere Neigung (20–25) und ein Gieren von 25–35 erzeugen für hohe Dinge (Türme, Flaschen, Lampen, Menschen) eine freundlichere „Produktaufnahme“. - Einfach und klobig: Wenige saubere Volumenkörper lesen sich besser als viele fummelige. Kleine Teile (Knöpfe, Füße, Schaltflächen) machen es realistisch: füge sie hinzu.
- Boden schaffen: Schatten sind automatisch. Etwas, das auf einem Brett, Tisch oder Unterteller steht, wirft seinen Schatten darauf. Ein Brett, Tablett, Hügel oder Tisch unter einem kleinen Objekt hilft ihm, im Raum zu stehen.
- Text: optional
k.title(...)oben links, plus kurze kleingeschriebene Randnotizen (k.label), die auf 3D-Punkte zeigen. Schreibe sie in der Sprache des Benutzers. Keine Kästen oder Sprechblasen über der Zeichnung. - Blatt: 1000×1000 standardmäßig. Für breite Szenen verwende
export const sheet = { width: 1200, height: 900 }.--transparententfernt das Papier. - Animationsgröße: 16 Frames bei 12 fps (eine 1,3 s Schleife) standardmäßig; ein typisches SVG ist 0,5–1 MB. Für eine langsame Bewegung verwende
sheet.fps = 8. Halteframes≤ 24.
Szenenvorlage
// Eine Teekanne auf einem Untersetzer; der Deckel klappert.
// Teil Aufruf Größe / Position Farbe
// Untersetzer cylinder r 120, h 10 wood
// Körper lathe { smooth } r 55→94→50, h 118, auf Untersetzer teal
// Ausguss tube [14, 7] von innen im Körper, nach links teal
// Griff tube 8 beide Enden innen im Körper, rechts teal
// Deckel+Knopf lathe + sphere in einer Gruppe, am hinteren Rand teal, ochre
export const sheet = { seed: 3 };
export function draw(k, t = 0) {
k.cylinder([0, 0, 0], 120, 10, { fill: 'wood' });
k.group({ rotate: { z: 45 } }, () => { // Ausguss nach links, Griff nach rechts
k.lathe([0, 0, 10], [[55, 0], [78, 10], [94, 45], [90, 85], [68, 112], [50, 118]], { fill: 'teal', smooth: true });
k.tube([[-78, 0, 50], [-112, 0, 66], [-128, 0, 100], [-146, 0, 118]], [14, 7], { fill: 'teal' });
k.tube([[70, 0, 112], [112, 0, 108], [122, 0, 72], [84, 0, 40]], 8, { fill: 'teal' });
const hop = Math.max(0, k.wave(0, 2 * t)); // 0..1, zwei Hüpfer pro Loop
k.group({ about: [44, 0, 128], rotate: { y: -18 * hop }, at: [0, 0, 16 * hop] }, () => {
k.lathe([0, 0, 127], [[52, 0], [50, 5], [30, 13], [8, 18], [0, 19]], { fill: 'teal', smooth: true });
k.sphere([0, 0, 152], 10, { fill: 'ochre' });
});
k.steam([-150, 0, 125], { h: 90, n: 2, spread: 18 });
});
k.label('klappernder Deckel', { to: [0, 0, 140], side: 'right' });
}