Was macht model-by-coding?
Erstelle ein 3D-Modell eines physischen Objekts aus Fotografien – vollständig in Code – und verwandle es in einen Zerlegefilm und ein GIF. Die Pipeline ist in einer Sache unnachgiebig: Das Modell wird bei jedem Schritt anhand der Fotos überprüft, sodass der Film das fotografierte Objekt zeigt und nicht nur ein plausibles Modell.
Wann verwenden
- Ein hartflächiges Produkt (Ventilator, Lampe, Lautsprecher, Kamera, Werkzeug, Küchengerät) soll in einem kurzen Video erklärt oder auseinandergebaut gezeigt werden.
- Das Objekt existiert physisch und kann aus mehreren Winkeln fotografiert werden.
- Die Ausgabe ist ein Endlosschleifen-Zerlegeclip für eine README, einen Beitrag oder eine Demo-Reel.
- Ein vorhandener Fotosatz muss in ein bearbeitbares, neu renderbares Modell umgewandelt werden – kein gescanntes Mesh.
Wann nicht verwenden
- Fotorealistische Darstellungen werden benötigt: Verwende Photogrammetrie oder einen 3D-Scanner.
- Das Objekt ist organisch, weich oder verformbar (Stoff, Pflanzen, Gesichter).
- Es sind keine Fotografien vorhanden, oder das Objekt ist nur in einem Video zu sehen.
- Ein einzelnes Standbild reicht aus – dann sind die HyperFrames-Schritte unnötig.
- Das Motiv ist eine Text-/UI-Animation: Diese Pipeline befasst sich mit Geometrie.
Pipeline
| Schritt | Ergebnis | Akzeptanzkriterium |
|---|---|---|
| 1. Messen | Eine Referenzmaßangabe, eine Verhältnistabelle, ein DIM-Objekt | Verhältnisse anhand ≥2 Fotos abgeglichen, jede Annahme als abgeschätzt markiert |
| 2. Modellieren | Eine codebasierte Three.js-Szene, ein IIFE-Bundle, die Betrachterseite | Montierter Zustand hat keine Lücken; p = 1 trennt jedes Teil |
| 3. Verifizieren | Sechs Vergleichsblätter (Foto/Render) in gleicher Pose | Silhouetten- und Merkmalsverhältnisse innerhalb der Toleranz auf allen sechs Blättern |
| 4. Filmen | Eine HyperFrames-Komposition, check-Bericht, Auslieferungs-MP4 | ok: true, keine Fehler, Dauer entspricht data-duration |
| 5. Schneiden | Ein Endlosschleifen-GIF | Beginnt und endet in stabilen Posen, unter ~1 MB |
Ein realistischer Zeitaufwand für ein Objekt beträgt einige Stunden bis zwei Tage, wobei der Großteil auf die Schritte 2–3 entfällt. Schritt 3 zu überspringen verwandelt eine Woche Modellierung in ein pünktlich geliefertes, aber falsches Modell.
Schritt 1 – Aus den Fotos messen
Sammle sechs Posen (Vorderseite, echte Seite, Rückseite, Rückseite 3/4, Oberseite, Unterseite), wähle eine große Abmessung als Referenz, messe sie mit einem radialen Scan und drücke alles andere als Verhältnis dazu aus. Zähle diskrete Merkmale (Rippen, Blätter, Speichen) anhand ihrer Winkelperiode, nicht mit dem Auge. Halte jede Zahl in einem einzigen DIM-Objekt mit einem Kommentar, der das Quellfoto benennt sowie angibt, ob es gemessen oder abgeschätzt ist; die absolute reale Größe ist eine Entscheidung, keine Messung.
Vertiefung: references/01-modeling.md §0–2.
Schritt 2 – In Code modellieren
Ein Szenenmodul mit reiner Zustands-API: create, setView, setExplode, setExplodeMap, setSpin, setHeadTilt, setLift, render, getAnchors, resize, dispose. Weltkonvention: Objekt zeigt in +Z, Basis auf y = 0, Meter. Baue Gehäuse als Drehprofile, das Gitter als flache Bänder (nicht runde Röhren), Blätter als parametrische Flächen und registriere jedes Teil über eine Funktion, die seine montierte Position, Explosionsversatz und Ankerversatz speichert. Benenne die Teile einmal; der Film, die Beschriftungen, die Anker und die Tonsteuerung beziehen sich alle auf diese Namen.
Vertiefung: references/01-modeling.md §3–6.
Schritt 3 – Gegen die Fotos verifizieren
Erstelle das Bundle mit esbuild, rendere einen Frame pro Pose in einem kopflosen Chrome und vergleiche jedes Rendering mit seinem Foto als nebeneinanderliegendes Blatt, das auf die Bounding Box des Objekts zugeschnitten ist. Lies Proportionen und Teilpositionierungen als Bruchteile der eigenen Box des Objekts; passe keine Kreise an Kanten auf geschäftigem Hintergrund an – die Anpassung würde sich an Hintergrundbögen festhalten. Sechs Posen, einige Iterationen pro Pose.
Vertiefung: references/03-verify.md.
Schritt 4 – Den Film rendern
Erstelle die Komposition nach dem HyperFrames-Vertrag: ein Wurzelkompositionselement mit data-duration, eine pausierte GSAP-Timeline bei window.__timelines["main"], Three.js nur über hf-seek neu gezeichnet (niemals über rAF/Timer), Medien mit eigener Zeitsteuerung als class="clip" mit data-start/data-duration, eine Audiomischung als Audio-Clip, Text ab 28 px oder größer, und das große Bundle als assets/vendor/*.min.js eingekauft. Schreibe die Shot-Liste, bevor du animierst; steuere Kamera, Explosion und Beschriftungen aus einem Regie-Skript, damit Audiocues seine Konstanten gemeinsam nutzen können. Führe check aus, lese den Bericht, dann render --quality delivery.
Vertiefung: references/02-render.md.
Schritt 5 – Das GIF schneiden
Wähle ein ruhiges Segment von 3–4 Sekunden (normalerweise die Explosions-Haltepose), schneide es mit gif-master (Breite 480, 12 fps, Loop) oder mit dem ffmpeg-Zwei-Durchgang-Palette-Befehl und überprüfe Größe, Frame-Anzahl und Loop vor dem Veröffentlichen. Vertiefung: references/04-gif.md, scripts/make_gif.md.
Harte Einschränkungen
Dies sind die Regeln, deren Verletzung die Pipeline zerstört; sie sind keine Stilvorlieben.
- Vertrag zuerst. Objekt zeigt in +Z, Basis auf y = 0, Meter, Kamera
target + dist * (sin(yaw)cos(pitch), sin(pitch), cos(yaw)cos(pitch)), yaw/pitch in Grad. Jedes Skript und der Film teilen ihn. - Reiner Zustand. Die Szenen-API muss denselben Zustand zu denselben Pixeln rendern. Keine Animationsschleife, keine Echtzeituhr, kein
Math.random()im Code, von dem der Frame abhängt. - Frame = f(t). Kamera, Explosion, Drehung, Beschriftungen, Karten und Ton sind alles Funktionen der Filmzeit; nichts anderes.
- Kompositionsvertrag.
data-composition-id,data-start,data-duration,data-width,data-heightam Wurzelelement; pausierte Timeline registriert alswindow.__timelines["<id>"]; Neuzeichnung innerhalb vonhf-seekmite.detail.time. - Clips. Medien mit eigenem Start und eigener Dauer (Audio, Video, Einschübe) tragen
class="clip",data-start,data-duration; Audio zusätzlichdata-track-index. DOM, das von der Timeline animiert wird, benötigt keine Clip-Attribute. - Lesbarkeit. Nichts Informatives unter 28 px bei 1080p (die Typografie-Untergrenze des Prüfers ist 28 px = 2,6 % der kurzen Seite).
- Eingekaufte Gewichte. three.js und GSAP als
.min.jsunterassets/vendor/; lokale Schriftarten; kein Netzwerk während des Renderings. - Skripte sind generisch. Kein Objektname, kein absoluter Pfad, kein persönliches Verzeichnis in
scripts/; jedes Skript muss aus einem frischen Checkout laufen. - Befehle verifizieren. Jeder Befehl und Parameter, der in Dokumente, Skripte oder den Film geschrieben wird, muss einmal gegen die festgelegten Versionen ausgeführt werden, bevor er vertrauenswürdig ist.
Referenz-Routing
| Aufgabe | Lies |
|---|---|
| Messen, Verhältnisse, Drehprofile, Gitter-/Blattparameter, Teile, Explosion, Anker | references/01-modeling.md |
| Kompositionsvertrag, Regie/Storyboard, Audio-Synchronisation, HyperFrames-Befehle und -Ausgaben | references/02-render.md |
| Screenshot-Schleife, Vergleichsblätter, Winkel lesen, der Kreis-Anpassungs-Fehler | references/03-verify.md |
| gif-master-Bedienungskarte, Credits, ffmpeg-GIF-Rezept | references/04-gif.md |
| Repository, GitHub-Release, Community-List-PR, YouTube/X | references/05-publish.md |
| Symptom → Ursache → Behebungskatalog (Licht, Schatten, Rippen, Type, Bundles, Chrome) | references/06-gotchas.md |
Mit dieser Skill ausgelieferte Werkzeuge:
| Datei | Rolle |
|---|---|
scripts/view.html | Einzelbild-Betrachter; Pose und Bundle aus Query-Parametern |
scripts/verify_sheet.py | Foto-vs-Render-vergleichendes Blatt (--photo --render --out --bbox) |
scripts/hf_read_check.py | Fasst einen HyperFrames-Prüfbericht zusammen; --fail-on-error für CI |
scripts/make_gif.md | Browser/ffmpeg-Bedienungskarte für das GIF |
Minimale ausführbare Sequenz
Die Befehle werden aus dem Repository-Root gegen das durchgearbeitete Beispiel in examples/fan/ ausgeführt; für ein neues Objekt ersetze src/scene.js, photos/ und video/. Arbeitsdateien gehen nach %TEMP%, sodass der Checkout sauber bleibt. Behalte die Parameter – es sind die verifizierten. Ausführung in PowerShell.
$work = Join-Path $env:TEMP "mbc-verify"; New-Item -ItemType Directory -Force $work | Out-Null
# 1. Szene bündeln (Vorlage für ein neues Objekt; benötigt installiertes `three`).
# Das Beispiel liefert sein Bundle bereits unter examples/fan/video/assets/vendor/fan.bundle.min.js aus,
# daher kann dieser Schritt für das Beispiel übersprungen werden.
npx --yes [email protected] src/scene.js --bundle --format=iife --global-name=Scene `
--minify --target=chrome120 --outfile=dist/scene.bundle.min.js
# 2. Screenshot einer Verifikationspose des Beispiels (1920x1080, frisches Profil pro Durchlauf)
$chrome = "C:\Program Files\Google\Chrome\Application\chrome.exe"
$png = Join-Path $work "front.png"
$udd = Join-Path $env:TEMP ("view-" + [guid]::NewGuid().ToString("N"))
& $chrome --headless=new --use-angle=d3d11 --window-size=1920,1080 `
--hide-scrollbars --virtual-time-budget=12000 `
--screenshot=$png --user-data-dir=$udd `
"file:///$($PWD.Path.Replace('\','/'))/scripts/view.html?bundle=../examples/fan/video/assets/vendor/fan.bundle.min.js&yaw=-10&pitch=12&dist=0.85&ty=0.185&fov=30&noshadow=1"
# 3. Dieses Rendering mit dem Frontfoto in derselben Pose vergleichen
python scripts/verify_sheet.py --photo examples/fan/reference/fan.jpg --render $png `
--out (Join-Path $work "front-sheet.png") --bbox "130,245,1195,1455"
# 4. Film gegen HyperFrames-Vertrag prüfen, dann Bericht lesen
Set-Location examples/fan/video
# benötigt assets/audio/mix.wav (Release-Asset; siehe examples/fan/README.md)
npx --yes [email protected] check --at 21.15,27.6,35.18
$report = Get-ChildItem .hyperframes/artifacts/checks/*.json `
| Sort-Object LastWriteTime | Select-Object -Last 1
python ../../../scripts/hf_read_check.py $report.FullName --fail-on-error
npx --yes [email protected] snapshot --at 29.6
# 5. Auslieferungsmaster rendern
npx --yes [email protected] render --quality delivery
Set-Location ../../..
# 6. GIF mit ffmpeg schneiden (Browser-Route: scripts/make_gif.md)
$mp4 = (Get-ChildItem examples/fan/video/renders/*.mp4 | Sort-Object LastWriteTime | Select-Object -Last 1).FullName
ffmpeg -hide_banner -loglevel error -y `
-ss 29.6 -t 3.8 -i "$mp4" `
-vf "fps=12,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse=dither=sierra2_4a" `
-loop 0 (Join-Path $work "teardown.gif")
Schritt 3 gibt die beiden Zuschneideboxen aus; der verifizierte Durchlauf gibt saved ...\front-sheet.png 1112x702 | photo (130, 245, 1195, 1455) | render (652, 264, 1252, 1080) aus.
Zu erwartende Ausgaben: check schreibt video/.hyperframes/artifacts/checks/<uuid>.json; snapshot schreibt video/.hyperframes/artifacts/snapshots/<uuid>/frame-00-at-29.6s.png; render schreibt video/renders/video_<YYYY-MM-DD>_<HH-MM-SS>.mp4 (etwa 36 MB bei 43,5 s mit 1920×1080/30 fps, ungefähr 2,5 Minuten Capturing mit einer Hardware-GPU).
Voraussetzungen
- Node.js (getestet mit 22.19.0) mit
npx; esbuild 0.24.2 über npx. - Python 3.11 (getestet mit 3.11.1) mit Pillow für das Vergleichsblatt; numpy optional.
- ffmpeg auf PATH (getestet mit einem Git-Build vom 28.12.2025).
- Chrome für Screenshots im kopflosen Modus (getestet mit 157.0.8103.40); der obige Pfad ist der Windows-Standard.
- HyperFrames, festgelegt auf 0.9.36 über
npx --yes [email protected]. checkundrendersteuern den kopflosen Chrome mit--browser-gpuauf Auto: Hardware-GPU falls vorhanden, sonst Software (SwiftShader);previewläuft mit GPU flüssiger.
Fertigstellungskriterien
- Sechs Vergleichsblätter sind lesbar akzeptabel, mit aufgelisteten und erklärten Abweichungen.
hf_read_check.py --fail-on-errorendet mit Exit-Code 0 beim finalen Prüfbericht.- Das Auslieferungs-MP4 existiert und seine Dauer entspricht dem
data-duration-Attribut der Komposition. - Das GIF läuft sauber in einer Schleife und ist klein genug zum Posten.
- Jeder Befehl in dieser Skill wurde einmal in einem frischen Checkout ausgeführt.