Communitygithub.com

model-by-coding

Utilisez lorsque vous devez transformer un objet réel en modèle 3D codé avec une vidéo de démontage rendue et un GIF en boucle — mesurez l'objet à partir de photographies, modélisez-le en code Three.js, vérifiez chaque pose avec des captures d'écran sans tête et rendez le film avec HyperFrames 0.9.36.

Qu'est-ce que model-by-coding ?

Ce skill construit un modèle 3D d'un objet physique à partir de photographies, entièrement en code, puis le transforme en film de démontage et en GIF. Le pipeline, conçu pour les surfaces dures (ventilateurs, lampes, appareils photo, etc.), insiste sur la vérification du modèle par rapport aux photos à chaque étape, garantissant que le film montre l'objet photographié et non une approximation. Il prend en charge l'ensemble du flux : mesure des dimensions à partir des photos, modélisation en Three.js, vérification par comparaison rendu/photo, rendu vidéo avec HyperFrames, et découpage du GIF. Le pipeline est strict : orientation +Z, base à y=0, API à état pur, composition contractuelle. Il est idéal pour créer des modèles modifiables et re-rendus à partir de photos existantes, mais ne convient pas aux objets organiques ni aux rendus photo-réalistes. Les outils inclus (scripts de vérification, visualiseur, lecteur de rapport HyperFrames) et une séquence exécutable minimale sont fournis pour une reproduction rapide.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Mng12345/model-by-coding/tree/main

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait model-by-coding ?

Construisez un modèle 3D d'un objet physique à partir de photographies, entièrement en code, puis transformez-le en film de démontage et en GIF. Le pipeline est exigeant sur un point : le modèle est vérifié par rapport aux photos à chaque étape, de sorte que le film montre l'objet qui a été photographié plutôt que quelque chose de plausible.

Quand l'utiliser

  • un produit à surface dure (ventilateur, lampe, enceinte, appareil photo, outil, appareil de cuisine) doit être expliqué ou présenté en pièces dans une courte vidéo ;
  • l'objet existe physiquement et peut être photographié sous plusieurs angles ;
  • le résultat est un clip de démontage en boucle pour un README, un post ou une démo ;
  • un ensemble de photos existant doit devenir un modèle modifiable et re-rendu — pas un maillage scanné.

Quand ne pas l'utiliser

  • des ressources photo-réalistes sont nécessaires : utilisez la photogrammétrie ou un scanner ;
  • l'objet est organique, mou ou se déforme (tissu, plantes, visages) ;
  • aucune photographie n'est disponible ou l'objet n'est visible que dans une vidéo ;
  • une seule image fixe suffit — les étapes HyperFrames sont alors inutiles ;
  • le sujet est une animation de texte/UI : ce pipeline concerne la géométrie.

Pipeline

étapeproduireporte de vérification
1. Mesurerune dimension de règle, un tableau de ratios, un objet DIMratios croisés sur ≥2 photos, chaque hypothèse marquée déduite
2. Modéliserune scène Three.js codée, un bundle IIFE, la page de visualisationl'état assemblé n'a pas de trous ; p = 1 sépare chaque pièce
3. Vérifiersix planches photo/rendu en même posesilhouettes et ratios de caractéristiques dans la tolérance sur les six
4. Filmerune composition HyperFrames, rapport check, MP4 de livraisonok: true, aucune erreur, durée correspond à data-duration
5. Couperun GIF en bouclecommence et se termine sur des poses stables, sous ~1 Mo

Un budget réaliste pour un objet est de quelques heures à deux jours, la majeure partie du temps dans les étapes 2–3. Sauter l'étape 3 transforme une semaine de modélisation en un mauvais modèle livré à l'heure.

Étape 1 — Mesurer à partir des photos

Collectez six poses (face, profil vrai, dos, dos 3/4, dessus, dessous), choisissez une grande dimension comme règle, mesurez-la avec un balayage radial, et exprimez tout le reste comme un ratio de celle-ci. Comptez les caractéristiques distinctes (nervures, pales, branches) à partir de leur période angulaire plutôt qu'à l'œil. Gardez chaque nombre dans un objet DIM avec un commentaire indiquant sa photo source et s'il est mesuré ou déduit ; la taille absolue dans le monde réel est une décision, pas une mesure.

Approfondissement : references/01-modeling.md §0–2.

Étape 2 — Modéliser en code

Un module de scène avec une API à état pur : create, setView, setExplode, setExplodeMap, setSpin, setHeadTilt, setLift, render, getAnchors, resize, dispose. Convention monde : objet face à +Z, base à y = 0, mètres. Construisez les boîtiers comme des profils de tour, la grille comme des rubans plats (pas de tubes ronds), les pales comme des feuilles paramétriques, et enregistrez chaque pièce via une fonction qui stocke sa position assemblée, son décalage d'explosion et son décalage d'ancrage. Nommez les pièces une fois ; le film, les étiquettes, les ancres et le son utilisent tous ces noms.

Approfondissement : references/01-modeling.md §3–6.

Étape 3 — Vérifier par rapport aux photos

Compilez le bundle avec esbuild, rendez une image par pose dans Chrome sans tête, et comparez chaque rendu avec sa photo sous forme de planche côte à côte recadrée à la boîte englobante de l'objet. Lisez les proportions et le placement des pièces comme des fractions de la propre boîte de l'objet ; n'ajustez pas de cercles aux bords sur un fond chargé — l'ajustement s'accroche aux arcs de fond. Six poses, quelques itérations chacune.

Approfondissement : references/03-verify.md.

Étape 4 — Rendre le film

Construisez la composition selon le contrat HyperFrames : un élément de composition racine avec data-duration, une timeline GSAP en pause à window.__timelines["main"], Three.js redessiné uniquement depuis hf-seek (jamais depuis rAF/timers), des médias avec leur propre timing marqués comme class="clip" avec data-start/data-duration, un mix audio comme clip audio, du texte à 28 px ou plus, et le gros bundle vendu sous assets/vendor/*.min.js. Écrivez la liste des plans avant d'animer ; pilotez la caméra, l'explosion et les étiquettes à partir d'un script de réalisateur afin que les repères audio puissent partager ses constantes. Exécutez check, lisez le rapport, puis render --quality delivery.

Approfondissement : references/02-render.md.

Étape 5 — Couper le GIF

Choisissez un segment stable de 3–4 s (généralement la tenue éclatée), coupez-le dans gif-master (largeur 480, 12 ips, boucle) ou avec la commande de palette en deux passes de ffmpeg, et vérifiez la taille, le nombre d'images et la boucle avant de publier. Approfondissement : references/04-gif.md, scripts/make_gif.md.

Contraintes strictes

Voici les règles qui brisent le pipeline lorsqu'elles sont violées ; ce ne sont pas des préférences de style.

  1. Contrat d'abord. Objet face à +Z, base à y = 0, mètres, caméra target + dist * (sin(yaw)cos(pitch), sin(pitch), cos(yaw)cos(pitch)), yaw/pitch en degrés. Chaque script et le film le partagent.
  2. État pur. L'API de la scène doit rendre le même état aux mêmes pixels. Pas de boucle d'animation, pas d'horloge système, pas de Math.random() dans le code dont dépend l'image.
  3. Trame = f(t). Caméra, explosion, rotation, étiquettes, cartes et son sont tous des fonctions du temps du film ; rien d'autre.
  4. Contrat de composition. data-composition-id, data-start, data-duration, data-width, data-height sur l'élément racine ; timeline en pause enregistrée comme window.__timelines["<id>"] ; redessin dans hf-seek en utilisant e.detail.time.
  5. Clips. Les médias avec leur propre début et durée (audio, vidéo, insertions) portent class="clip", data-start, data-duration ; l'audio en plus data-track-index. Le DOM animé par la timeline n'a pas besoin d'attributs de clip.
  6. Lisibilité. Rien d'informatif en dessous de 28 px à 1080p (le seuil de type du vérificateur est 28 px = 2,6 % du petit côté).
  7. Poids vendus. three.js et GSAP comme .min.js sous assets/vendor/ ; polices locales ; pas de réseau pendant le rendu.
  8. Les scripts sont génériques. Pas de nom d'objet, pas de chemin absolu, pas de répertoire personnel dans scripts/ ; chaque script doit fonctionner à partir d'un checkout frais.
  9. Commandes de vérification. Chaque commande et paramètre écrit dans les docs, les scripts ou le film doit être exécuté une fois contre les versions épinglées avant d'être fiable.

Routage des références

tâchelire
mesure, ratios, profils de tour, paramètres grille/pale, pièces, explosion, ancresreferences/01-modeling.md
contrat de composition, storyboard/réalisateur, synchronisation audio, commandes et sorties HyperFramesreferences/02-render.md
boucle de capture d'écran, planches de comparaison, lecture des angles, l'échec d'ajustement de cerclereferences/03-verify.md
fiche d'opération gif-master, crédits, recette GIF ffmpegreferences/04-gif.md
dépôt, publication GitHub, PR de liste communautaire, YouTube/Xreferences/05-publish.md
catalogue symptôme → cause → correctif (éclairage, ombres, nervures, type, bundles, Chrome)references/06-gotchas.md

Outils fournis avec ce skill :

fichierrôle
scripts/view.htmlvisualiseur d'image unique ; pose et bundle depuis les paramètres de requête
scripts/verify_sheet.pyplanche côte à côte photo-vs-rendu (--photo --render --out --bbox)
scripts/hf_read_check.pyrésumer un rapport de vérification HyperFrames ; --fail-on-error pour CI
scripts/make_gif.mdfiche d'opération navigateur/ffmpeg pour le GIF

Séquence exécutable minimale

Les commandes s'exécutent depuis la racine du dépôt par rapport à l'exemple travaillé dans examples/fan/ ; pour un nouvel objet, remplacez src/scene.js, photos/ et video/. Les fichiers de travail vont dans %TEMP% pour que le checkout reste propre. Gardez les paramètres — ce sont ceux vérifiés. Exécutez dans PowerShell.

$work = Join-Path $env:TEMP "mbc-verify"; New-Item -ItemType Directory -Force $work | Out-Null

# 1. bundle de la scène (modèle pour un nouvel objet ; nécessite `three` installé).
#    L'exemple fournit son bundle à examples/fan/video/assets/vendor/fan.bundle.min.js,
#    donc cette étape peut être ignorée pour l'exemple.
npx --yes [email protected] src/scene.js --bundle --format=iife --global-name=Scene `
  --minify --target=chrome120 --outfile=dist/scene.bundle.min.js

# 2. capture d'écran d'une pose de vérification de l'exemple (1920x1080, profil frais par exécution)
$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. comparer ce rendu avec la photographie de face dans la même pose
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. vérifier le film par rapport au contrat HyperFrames, puis lire le rapport
Set-Location examples/fan/video
# nécessite assets/audio/mix.wav (asset de version ; voir 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. rendre le master de livraison
npx --yes [email protected] render --quality delivery
Set-Location ../../..

# 6. couper le GIF avec ffmpeg (route navigateur : 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")

L'étape 3 imprime les deux boîtes de recadrage ; l'exécution vérifiée imprime saved ...\front-sheet.png 1112x702 | photo (130, 245, 1195, 1455) | render (652, 264, 1252, 1080).

Sorties attendues : check écrit video/.hyperframes/artifacts/checks/<uuid>.json ; snapshot écrit video/.hyperframes/artifacts/snapshots/<uuid>/frame-00-at-29.6s.png ; render écrit video/renders/video_<YYYY-MM-DD>_<HH-MM-SS>.mp4 (environ 36 Mo pour 43,5 s à 1920×1080/30 ips, environ 2,5 minutes de capture avec un GPU matériel).

Prérequis

  • Node.js (testé 22.19.0) avec npx ; esbuild 0.24.2 via npx.
  • Python 3.11 (testé 3.11.1) avec Pillow pour la planche ; numpy optionnel.
  • ffmpeg sur PATH (testé avec une build git du 2025-12-28).
  • Chrome pour les captures d'écran sans tête (testé 157.0.8103.40) ; le chemin ci-dessus est le chemin par défaut Windows.
  • HyperFrames épinglé à 0.9.36 via npx --yes [email protected].
  • check et render pilotent Chrome sans tête avec --browser-gpu en automatique : GPU matériel quand présent, logiciel (SwiftShader) sinon ; preview est plus fluide avec un GPU.

Définition de terminé

  • six planches de comparaison lisibles de manière acceptable, avec les écarts listés et expliqués ;
  • hf_read_check.py --fail-on-error sort 0 sur le rapport de vérification final ;
  • le MP4 de livraison existe et sa durée est égale au data-duration de la composition ;
  • le GIF boucle proprement et est assez petit pour être publié ;
  • chaque commande de ce skill a été exécutée une fois dans un checkout frais.

Skills associés