Communitygithub.com

model-by-coding

Use quando um objeto real deve se tornar um modelo 3D construído em código com um vídeo de desmontagem renderizado e um GIF em loop — meça o objeto a partir de fotografias, modele-o em código Three.js, verifique cada pose em relação às fotos com capturas de tela headless e renderize o filme com HyperFrames 0.9.36.

O que é model-by-coding?

Este skill permite que um agente de IA transforme um objeto físico fotografado em um modelo 3D preciso, renderizado inteiramente em código, e produza um vídeo de desmontagem (teardown) em loop e um GIF. Ele é ideal para objetos de superfície dura como ventiladores, luminosas, alto-falantes, câmeras, ferramentas e eletrodomésticos. O processo segue um pipeline de cinco etapas: medição do objeto a partir de fotos, modelagem em Three.js com uma API de estado puro, verificação rigorosa comparando renderizações com as fotos originais por meio de capturas de tela headless (Chrome), renderização do filme com HyperFrames 0.9.36 e geração do GIF final. O skill é compatível com Claude Code, Cursor, Codex e outros agentes que executam comandos no terminal e scripts Python/Node.js. Ele é particularmente útil quando um conjunto de fotos existente precisa se tornar um modelo editável e re-renderizável — não uma malha escaneada — e o resultado deve ser validado visualmente contra as referências fotográficas em cada etapa.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que model-by-coding faz?

Construa um modelo 3D de um objeto físico a partir de fotografias, inteiramente em código, e depois transforme-o em um filme de desmontagem e um GIF. O pipeline é opinativo em uma questão: o modelo é verificado em relação às fotos em cada etapa, para que o filme mostre o objeto que foi fotografado, e não algo plausível.

Quando usar

  • um produto de superfície dura (ventilador, luminária, alto-falante, câmera, ferramenta, eletrodoméstico) deve ser explicado ou mostrado em partes em um vídeo curto;
  • o objeto existe fisicamente e pode ser fotografado de vários ângulos;
  • a saída é um clipe de desmontagem em loop para um README, uma postagem ou um demo reel;
  • um conjunto de fotos existente deve se tornar um modelo editável e re-renderizável — não uma malha escaneada.

Quando não usar

  • são necessários assets fotorrealistas: use fotogrametria ou um scanner;
  • o objeto é orgânico, macio ou deformável (tecido, plantas, rostos);
  • não há fotografias disponíveis, ou o objeto só é visível em um vídeo;
  • uma única imagem estática é suficiente — as etapas do HyperFrames são desnecessárias;
  • o assunto é uma animação de texto/UI: este pipeline é sobre geometria.

Pipeline

etapaproduzircritério de aceitação
1. Mediruma dimensão de régua, uma tabela de proporções, um objeto DIMproporções verificadas em ≥2 fotos, toda suposição marcada como inferida
2. Modelaruma cena Three.js construída em código, um bundle IIFE, a página do visualizadorestado montado não tem lacunas; p = 1 separa cada parte
3. Verificarseis folhas de comparação foto/renderização na mesma poseproporções de silhueta e características dentro da tolerância em todas as seis
4. Filmaruma composição HyperFrames, relatório check, MP4 de entregaok: true, sem erros, duração corresponde a data-duration
5. Cortarum GIF em loopcomeça e termina em poses estabilizadas, abaixo de ~1 MB

Um orçamento realista para um objeto é de algumas horas a dois dias, a maior parte nas etapas 2–3. Pular a etapa 3 é o que transforma uma semana de modelagem em um modelo errado entregue no prazo.

Etapa 1 — Medir a partir das fotos

Colete seis poses (frente, lado verdadeiro, costas, costas 3/4, topo, base), escolha uma dimensão grande como régua, meça-a com uma varredura radial e expresse tudo mais como uma proporção dela. Conte características discretas (nervuras, pás, raios) a partir de seu período angular, e não visualmente. Mantenha cada número em um objeto DIM com um comentário nomeando sua foto de origem e se é medido ou inferido; o tamanho absoluto do mundo real é uma decisão, não uma medição.

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

Etapa 2 — Modelar em código

Um módulo de cena com uma API de estado puro: create, setView, setExplode, setExplodeMap, setSpin, setHeadTilt, setLift, render, getAnchors, resize, dispose. Convenção mundial: objeto voltado para +Z, base em y = 0, metros. Construa carcaças como perfis de torno, a grade como fitas planas (não tubos redondos), pás como folhas paramétricas e registre cada parte por meio de uma função que armazena sua posição montada, deslocamento de explosão e deslocamento de âncora. Nomeie as partes uma vez; o filme, rótulos, âncoras e som dependem desses nomes.

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

Etapa 3 — Verificar em relação às fotos

Compile o bundle com esbuild, renderize um quadro por pose no Chrome headless e compare cada renderização com sua foto como uma folha lado a lado cortada para a caixa delimitadora do objeto. Leia proporções e posicionamento de partes como frações da própria caixa do objeto; não ajuste círculos a bordas em um fundo complexo — o ajuste se prende a arcos de fundo. Seis poses, algumas iterações cada.

Profundidade: references/03-verify.md.

Etapa 4 — Renderizar o filme

Construa a composição conforme o contrato do HyperFrames: um elemento raiz de composição com data-duration, uma timeline GSAP pausada em window.__timelines["main"], Three.js redesenhado apenas a partir de hf-seek (nunca de rAF/timers), mídia com seu tempo próprio marcada como class="clip" com data-start/data-duration, um mix de áudio como um clipe de áudio, texto com 28 px ou maior, e o bundle grande fornecido como assets/vendor/*.min.js. Escreva a lista de cenas antes de animar; direcione câmera, explosão e rótulos a partir de um único script do diretor para que as dicas de áudio possam compartilhar suas constantes. Execute check, leia o relatório, depois render --quality delivery.

Profundidade: references/02-render.md.

Etapa 5 — Cortar o GIF

Escolha um segmento estável de 3–4 s (geralmente a parada explodida), corte-o com gif-master (largura 480, 12 fps, loop) ou com o comando de paleta de dois passos do ffmpeg, e verifique tamanho, contagem de quadros e loop antes de publicar. Profundidade: references/04-gif.md, scripts/make_gif.md.

Restrições rígidas

Estas são as regras que quebram o pipeline quando violadas; não são preferências de estilo.

  1. Contrato primeiro. Objeto voltado para +Z, base em y = 0, metros, câmera target + dist * (sin(yaw)cos(pitch), sin(pitch), cos(yaw)cos(pitch)), yaw/pitch em graus. Todo script e o filme compartilham isso.
  2. Estado puro. A API da cena deve renderizar o mesmo estado nos mesmos pixels. Nenhum loop de animação, nenhum relógio de parede, nenhum Math.random() em código do qual o quadro dependa.
  3. Quadro = f(t). Câmera, explosão, rotação, rótulos, cards e som são funções do tempo do filme; nada mais.
  4. Contrato de composição. data-composition-id, data-start, data-duration, data-width, data-height no elemento raiz; timeline pausada registrada como window.__timelines["<id>"]; redesenho dentro de hf-seek usando e.detail.time.
  5. Clipes. Mídia com seu próprio início e duração (áudio, vídeo, inserções) carrega class="clip", data-start, data-duration; áudio adicionalmente data-track-index. DOM animado pela timeline não precisa de atributos de clipe.
  6. Legibilidade. Nada informacional abaixo de 28 px em 1080p (piso de tipo do verificador é 28 px = 2,6% do lado menor).
  7. Pesos fornecidos. three.js e GSAP como .min.js em assets/vendor/; fontes locais; nenhuma rede durante a renderização.
  8. Scripts são genéricos. Nenhum nome de objeto, nenhum caminho absoluto, nenhum diretório pessoal em scripts/; cada script deve ser executado a partir de um checkout limpo.
  9. Verificar comandos. Todo comando e parâmetro escritos em docs, scripts ou no filme deve ser executado uma vez contra as versões fixadas antes de ser confiável.

Roteamento de referência

tarefaleia
medição, proporções, perfis de torno, parâmetros de grade/lâmina, partes, explosão, âncorasreferences/01-modeling.md
contrato de composição, diretor/storyboard, sincronia de áudio, comandos e saídas do HyperFramesreferences/02-render.md
loop de captura de tela, folhas de comparação, leitura de ângulos, falha do ajuste de círculoreferences/03-verify.md
cartão de operação do gif-master, créditos, receita de GIF do ffmpegreferences/04-gif.md
repositório, GitHub Release, PR da lista da comunidade, YouTube/Xreferences/05-publish.md
catálogo sintoma → causa → correção (iluminação, sombras, nervuras, tipo, bundles, Chrome)references/06-gotchas.md

Ferramentas fornecidas com este skill:

arquivofunção
scripts/view.htmlvisualizador de quadro único; pose e bundle a partir de parâmetros de consulta
scripts/verify_sheet.pyfolha lado a lado foto-vs-renderização (--photo --render --out --bbox)
scripts/hf_read_check.pyresumir um relatório de verificação do HyperFrames; --fail-on-error para CI
scripts/make_gif.mdcartão de operação para navegador/ffmpeg do GIF

Sequência mínima executável

Os comandos são executados a partir da raiz do repositório contra o exemplo trabalhado em examples/fan/; para um novo objeto, substitua src/scene.js, photos/ e video/. Os arquivos de trabalho vão para %TEMP% para que o checkout permaneça limpo. Mantenha os parâmetros — eles são os verificados. Execute no PowerShell.

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

# 1. compilar o bundle (modelo para um novo objeto; precisa do `three` instalado).
#    O exemplo já fornece o bundle em examples/fan/video/assets/vendor/fan.bundle.min.js,
#    então esta etapa pode ser pulada para o exemplo.
npx --yes [email protected] src/scene.js --bundle --format=iife --global-name=Scene `
  --minify --target=chrome120 --outfile=dist/scene.bundle.min.js

# 2. capturar uma pose de verificação do exemplo (1920x1080, perfil novo por execução)
$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. comparar essa renderização com a fotografia frontal na mesma 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. verificar o filme contra o contrato do HyperFrames, depois ler o relatório
Set-Location examples/fan/video
# precisa de assets/audio/mix.wav (Release asset; veja 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. renderizar o master de entrega
npx --yes [email protected] render --quality delivery
Set-Location ../../..

# 6. cortar o GIF com ffmpeg (rota do navegador: 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")

A etapa 3 imprime as duas caixas de corte; a execução verificada imprime saved ...\front-sheet.png 1112x702 | photo (130, 245, 1195, 1455) | render (652, 264, 1252, 1080).

Saídas esperadas: check escreve video/.hyperframes/artifacts/checks/<uuid>.json; snapshot escreve video/.hyperframes/artifacts/snapshots/<uuid>/frame-00-at-29.6s.png; render escreve video/renders/video_<YYYY-MM-DD>_<HH-MM-SS>.mp4 (cerca de 36 MB para 43,5 s em 1920×1080/30 fps, aproximadamente 2,5 minutos de captura com uma GPU de hardware).

Requisitos

  • Node.js (testado 22.19.0) com npx; esbuild 0.24.2 via npx.
  • Python 3.11 (testado 3.11.1) com Pillow para as folhas; numpy opcional.
  • ffmpeg no PATH (testado com uma build git de 2025-12-28).
  • Chrome para capturas de tela headless (testado 157.0.8103.40); o caminho acima é o padrão do Windows.
  • HyperFrames fixado em 0.9.36 via npx --yes [email protected].
  • check e render usam Chrome headless com --browser-gpu no automático: GPU de hardware quando presente, software (SwiftShader) caso contrário; preview é mais suave com uma GPU.

Definição de pronto

  • seis folhas de comparação são lidas de forma aceitável, com os desvios listados e explicados;
  • hf_read_check.py --fail-on-error sai com 0 no relatório de verificação final;
  • o MP4 de entrega existe e sua duração é igual ao data-duration da composição;
  • o GIF faz loop limpo e é pequeno o suficiente para publicar;
  • todo comando neste skill foi executado uma vez em um checkout novo.

Habilidades Relacionadas