bugeng777/teardown

Construa um simulador 3D interativo de uma máquina ou mecanismo real (um motor, um trem de pouso, uma articulação ambulante, uma bomba, uma caixa de engrenagens) como uma única página HTML offline que pode ser desmontada, com painéis ao vivo conduzidos pelo mesmo modelo que move as peças, um botão para cada subsistema, cortes, vistas de câmera e um tour automático que entrega o controle ao visitante; depois grave quadro a quadro em um vídeo de 60 fps com uma trilha procedural sincronizada.

O que é teardown?

Teardown é uma habilidade de IA que gera um simulador 3D interativo e offline de uma máquina ou mecanismo real, tudo em uma única página HTML. Ao receber uma solicitação do tipo 'como funciona um motor V8?', a habilidade constrói um modelo 3D completo com painéis que mostram dados reais, permite isolar peças, fazer cortes e oferece um tour automático. A ferramenta também é capaz de gravar o tour em um vídeo de 60 fps com uma trilha sonora procedural perfeitamente sincronizada, usando um sistema de timeline comum. A habilidade foi portada para Cursor por bugeng777, com suporte a construção e renderização local, e inclui exemplos prontos de um motor V8, um trem de pouso Cessna e um Strandbeest de Jansen. Todo o processo é baseado em regras rigorosas de engenharia reversa a partir de referências reais, garantindo que cada dimensão e movimento sejam precisos e verificáveis.

Funciona com✓Claude Code~Codex CLI✓Cursor
npx skills add bugeng777/teardown-cursor

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

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

Documentação

O que teardown faz?

Uma máquina, uma página. O visitante vê a coisa funcionar, pressiona um botão e a parte que está trabalhando se abre enquanto os medidores ao redor mostram os números reais. Quando deixado sozinho, a página faz um tour automático com um cursor. O mesmo código grava um filme do tour, quadro a quadro, com uma trilha construída na mesma linha do tempo.

SKILL_DIR abaixo é a pasta onde este arquivo reside (para uma instalação no Cursor, geralmente ~/.cursor/skills/teardown, ~/.agents/skills/teardown ou .cursor/skills/teardown dentro de um projeto). As compilações e renderizações vão para ./teardown-out da pasta de onde você executa.

Primeira execução

cd "$SKILL_DIR" && npm install && npx playwright install chromium

As páginas não precisam de mais nada. O vídeo precisa do ffmpeg no PATH e a trilha precisa do Python 3 (apenas biblioteca padrão). Defina FFMPEG, PYTHON ou CHROMIUM para apontar para outros binários.

Os 3 exemplos

Construa um, abra o HTML, pressione botões. Copie o mais próximo ao começar uma nova máquina.

A máquinaO que a impulsionaVale a pena roubar
v8-*Um V8 cross-plane com camisas de vidro: a carga queima dentro do cilindro que você acompanha, válvulas sobem em seus cames, 8 pistões se movem a partir do exato mecanismo biela-manivela.Ângulo do virabrequim. Ordem de ignição 1-8-4-3-6-5-7-2, um modelo de pressão na câmara para o diagrama indicador.Modos de corte (vidro, seção, sólido), a ordem de ignição como um seletor de cilindros, gráficos ao vivo sincronizados com o virabrequim.
cessna-*O trem de pouso principal do Cessna 337 se recolhendo na fuselagem na decolagem e descendo no pouso.Curso 0..1: uma cremalheira de 201 mm gira um pinhão de 32 dentes (módulo 4 mm) em exatos 180°.Um grau de liberdade posando um mecanismo inteiro, fases de voo como funções do tempo, uma pista que rola sob o modelo.
strandbeest-*O Strandbeest de Theo Jansen, 20 pernas em um único virabrequim, andando de lado sobre a areia.Vento. A velocidade do virabrequim é integrada a partir dele; cada articulação segue por interseção de círculos a partir dos 11 comprimentos de elos de Jansen.Um solucionador de ligações exato em 67 linhas, tubos instanciados, traços dos pés, um gráfico de contato de todos os 20 pés.

Cada um vem em 3 pastas: <nome>-shared/ contém a máquina, <nome>-film/ o tour gravado, <nome>-live/ a página que você dirige.

node "$SKILL_DIR/sims/build.mjs" v8-live          # → teardown-out/dist/v8-live.html, offline, ~800 KB
node "$SKILL_DIR/sims/build.mjs"                  # todos os 6

Como uma máquina é construída

Uma pasta por máquina, dividida por função. Os exemplos seguem isto exatamente:

ArquivoFunção
kin.js / gear.js / jansen.jsA matemática. Dimensões reais em unidades reais, uma entrada (ângulo do virabrequim, curso, vento) e cada pose e leitura em função dela. Sem three.js aqui.
engine.js / gear.js / beast.jsA geometria, construída a partir de código: peças torneadas, tubos, elos instanciados. update(input) a posiciona.
stage.jsEstúdio, luzes, sombras, pós-processamento (GTAO, bloom). frame(state, cam) desenha um quadro.
console.jsA sobreposição: layout CSS fixo de 1600 x 900 com painéis, gráficos, alternadores, chamadas com linhas guia. update(state) redesenha a partir do estado do quadro.
film.jsUm SCRIPT de movimentos do operador (vistas, isolar, corte, acelerador) e render(t) como uma função pura do tempo.
live.jsA mesma máquina em tempo real: botões, controles deslizantes, órbita, zoom, teclas. Sem entrada, executa o script de film.js como um tour automático com um cursor; qualquer clique, arrasto, roda ou tecla entrega o controle, 25 s de inatividade o devolvem.
score.pyO som na linha do tempo do filme.

Para uma máquina fora de SKILL_DIR, crie uma pasta com um main.js e importe o kit pelo nome: import {runSim} from 'teardown-kit/runtime.js'. Compile com node "$SKILL_DIR/sims/build.mjs" ./my-machine.

Regras que decidem se funciona

  1. Comece de uma referência, nunca da imaginação. Uma foto, um desenho em corte de um manual, um clipe da coisa real. Construa contra ela e compare quadro a quadro. Máquinas inventadas a partir de uma frase saem genéricas toda vez; o mesmo modelo reconstrói uma real de perto quando tem algo para corresponder.
  2. Números reais, uma fonte. Obtenha as dimensões reais primeiro (diâmetro do cilindro, curso, número de dentes, comprimentos dos elos). Cada medidor, gráfico e rótulo lê da mesma função que posiciona as peças, então nada na tela pode discordar do movimento. Verifique um manualmente: no Cessna, 32 dentes × módulo 4 mm é um diâmetro primitivo de 128 mm, e metade de sua circunferência é o curso de 201 mm.
  3. Uma entrada impulsiona tudo. Pose a partir do ângulo do virabrequim, do curso ou do vento. Nada é animado manualmente, então o filme, a página ao vivo e a trilha nunca divergem.
  4. A parte que está trabalhando se abre. Isole-a, corte-a, faça um raio-X. Uma câmera que entra por dentro vale mais do que dez órbitas.
  5. Estúdio de luz, um acento. Fundos claros são lidos em um feed; escuros perdem o primeiro segundo. O acento marca a coisa que está mudando. Cuidado com peças quase brancas em um fundo claro: dê a elas um contorno a tinta ou um solo mais escuro.
  6. Escolha a câmera para o mecanismo. Uma ligação planar vista de frente colapsa em uma treliça; uma vista 3/4 ao longo da espinha mantém cada perna legível.
  7. Corrija colisões com um número. Quando uma parte atravessa outra, escale ou mova-a no bloco de parâmetros. Nunca a esconda com a câmera.

Regras da página ao vivo

  • Teste em uma GPU integrada. Uma página que roda a 60 fps em uma placa de desktop pode cair para 15 fps na placa integrada de um laptop. Os exemplos carregam níveis de qualidade (TIERS em live.js): sem AO, menor proporção de pixels, mapas de sombra menores, painéis redesenhados a cada dois quadros. Encontre o shader caro primeiro: um deslocamento computado 5 vezes por vértice custa mais do que todos os níveis juntos.
  • Aqueça os shaders. kit/warm.js compila cada programa em paralelo antes do primeiro quadro, para que a página nunca congele na primeira renderização.
  • Mantenha a página abaixo de 1 MB. Rastreadores de links (X, Slack) leem o cartão de compartilhamento do HTML e desistem de uma página de 15 MB. Modelos grandes vão como arquivos ao lado da página: build.json → {"external": {"heavy.glb": "light.glb"}}.

Contrato render(t)

import {runSim} from '../kit/runtime.js';

const DEFAULTS = {duration: 20, fps: 60, hud: {enabled: false}, director: {enabled: false}};

runSim(DEFAULTS, async ({cfg, canvas, capture}) => {
  // construir a cena, pré-computar qualquer coisa com estado
  return {render(t) { /* desenhar quadro t do zero */ return {}; }, resize() {}};
});
  • render(t) é puro: sem Math.random (use rng(seed) de kit/util.js na configuração), sem Date, sem estado carregado entre quadros. A captura o chama em momentos arbitrários.
  • Qualquer coisa que se mova por suas próprias regras (agentes, partículas) é simulada uma vez no carregamento em arrays tipados; render apenas os lê. Uma quantidade integrada ao longo do tempo (o virabrequim do Strandbeest sob um vento variável) é integrada em forma fechada ou tabulada no carregamento.
  • Cada batida vai para <nome>-film/timeline.json em segundos. A trilha lê o mesmo arquivo.
  • O quadro 0 é a miniatura. Ela já deve mostrar a máquina.

Comandos

node "$SKILL_DIR/sims/build.mjs" v8-film
node "$SKILL_DIR/sims/capture.mjs" v8-film --size 1600x900 --dpr 1.2 --stills beats --cols 4 --out teardown-out/v8-beats.png
node "$SKILL_DIR/sims/capture.mjs" v8-film --size 1600x900 --dpr 1.2 --still 12.5 --out teardown-out/v8-12.5.png
node "$SKILL_DIR/sims/capture.mjs" v8-film --size 1600x900 --dpr 1.2 --out teardown-out/v8-silent.mp4
python "$SKILL_DIR/run_sfx.py" "$SKILL_DIR/sims/v8-shared/score.py"
ffmpeg -y -i teardown-out/v8-silent.mp4 -i teardown-out/v8-score.wav -map 0:v -map 1:a -c:v copy -c:a aac -b:a 256k -shortest -movflags +faststart teardown-out/v8.mp4
node "$SKILL_DIR/wave.mjs" teardown-out/v8.mp4 --timeline "$SKILL_DIR/sims/v8-film/timeline.json"

--size é o layout CSS e --dpr o multiplica: 1600 x 900 a 1.2 dá 1920 x 1080. A captura imprime a GPU que obteve; um renderizador por software significa que as flags de GPU em paths.mjs não funcionaram.

Loop de revisão

Você não pode assistir ao vídeo; você pode olhar para quadros. Nunca relate uma máquina como concluída sem ler folhas da renderização atual.

  1. --stills beats: um mosaico por batida da linha do tempo, 0,3 s após ela, cada um rotulado t=.
  2. Leia cada mosaico contra a lista de verificação abaixo.
  3. Amplie: --stills every:0.2 --from A --to B para uma transição, --still T para um quadro completo.
  4. Corrija, reconstrua, volte ao passo 1. Pare quando uma passagem completa não encontrar nada.
  5. Final: node "$SKILL_DIR/sheet.mjs" --video <final.mp4> --timeline <timeline.json> e leia também: mostra o que o codificador escreveu.

Lista de verificação:

  • O mecanismo. Cada parte que deveria tocar toca; nada passa através de nada; os números nos painéis correspondem à pose.
  • Composição. Um ponto focal por quadro. Nada importante a menos de 60 px de uma borda. Rótulos nunca cobrem a parte que nomeiam.
  • Tipografia. Nada cortado. A leitura principal é legível na largura de um telefone.
  • 3D. Bloom come detalhes: mantenha camadas emissivas abaixo de 1.0. Superfícies quase brancas estouram. Metal brilhante sob pouca luz cria estrias: aspereza ≥ 0.45 e envMapIntensity ≈ 0.5 em superfícies grandes.
  • Tempo. Cada estado se mantém tempo suficiente para ser lido: 1 s para uma frase curta mais 0,25 s por palavra além de três.

Armadilhas do three.js que os exemplos já encontraram

  • smoothstep(a, b, x) com a > b retorna 0 no Windows (ANGLE/D3D). Escreva 1.0 - smoothstep(b, a, x).
  • Um ShadowMaterial ou um decalque a uma fração de milímetro acima do chão perde o teste de profundidade dentro de um alvo de renderização de pós-processamento. Dê a ele polygonOffset.
  • Um quadrado colocado no chão com um mapeamento espelhado é descartado como face traseira. Use DoubleSide.
  • Um pixel NaN escurece todo o quadro através do bloom. Aperte cada base de pow() em um shader.
  • GTAO em um modelo cortado (cutaway) precisa dos mesmos planos de recorte em gtao.normalMaterial, ou a metade cortada retorna como um fantasma pálido.

Som

sfx/ sintetiza cada som em Python puro (48 kHz, reproduzível) e lê a linha do tempo do filme, para que o som nunca saia de sincronia. python "$SKILL_DIR/run_sfx.py" --list mostra os geradores. sample() adiciona os sons CC0 gravados em sfx/samples/. sfx/score_kit.py tem as camadas e acentos que as 3 trilhas usam: uma camada de acorde, um baque suave por curso de potência, um motor, ar sob arrasto.

  • Cada tempo vem da linha do tempo, nunca de um número digitado.
  • A masterização é automática: −14 LUFS, pico verdadeiro ≤ −2 dBFS.
  • Acento, nunca narre: movimento contínuo permanece em silêncio. Uma nota para cada som tonal.

Gosto, com números

  • Suavização: entradas cubic-bezier(0.16, 1, 0.3, 1), saídas cubic-bezier(0.6, 0, 0.9, 0.35) com metade da duração da entrada, estado a estado cubic-bezier(0.65, 0, 0.35, 1). Linear apenas para movimento contínuo.
  • A máquina preenche 60-70% de sua viewport. Rótulos nunca abaixo de 34 px em uma tela de 1080.
  • Um acento, e ele significa algo: a parte que está trabalhando agora.
  • Nada parado: um elemento sempre vivo.

Créditos

Port para Cursor por bugeng777/teardown-cursor de elvarofficial/teardown (MIT). O kit, captura de quadros, motor de som e regras de revisão vêm de whaleyxbt/claude-motion (MIT). As amostras gravadas são CC0 do Freesound, editadas por Barty-Bart/motion-graphics (MIT); fontes em sfx/samples/SOURCES.md.

Habilidades Relacionadas