Skill de Máquina
Você constrói uma máquina como um estúdio de produto a fotografa e um engenheiro a explica: a coisa real em seu tamanho real, com materiais reais, em um cenário de estúdio limpo, funcionando com equações reais. Uma linha de entrada, um arquivo HTML de saída e um filme em um comando.
A saída é sempre:
<nome>.html: uma página auto-contida (three.js 0.170 via jsDelivr, o kit inline). Ela abre a partir do disco, de qualquer host estático ou dentro de um iframe.- Um filme:
node scripts/record.mjs <nome>.html out/<nome>.mp4 --music freepd:<Categoria>/<Nome>.
Abra examples/ primeiro. Cada exemplo foi feito a partir da única linha no topo de sua página. examples/turbofan.html é a referência: leia-a de ponta a ponta antes de escrever qualquer coisa.
O padrão
Antes de começar, imagine o quadro que um espectador vê após três segundos. Já deve parecer uma fotografia de estúdio do produto da máquina real: silhueta e proporções corretas, metal que parece metal, uma sombra suave em um chão de papel, nada flutuando, nada cortando, nada provisório. Então ela se move, e cada número na tela é computado.
Um resultado não está pronto enquanto qualquer uma destas condições for verdadeira:
- faltar uma peça que um mecânico esperaria ver (sem bicos de combustível em um combustor, sem escape em um relógio, sem válvulas em um motor)
- algo flutuar, intersectar ou ter uma emenda ou lacuna visível em uma junta
- um material parecer plástico quando deveria ser metal, ou tudo ser um cinza só
- um número na tela ser digitado em vez de computado pelo resolvedor
- o corte mostrar cascas ocas em vez de faces de seção sólidas
- o primeiro quadro do filme não ser bonito
Fluxo de trabalho
1. Pesquise a máquina real (5 minutos, sem código)
Escreva, em um bloco de comentário no topo do script da máquina, a partir do que você sabe (e da web, se tiver):
- As dimensões reais em metros das 5 a 10 peças que definem a silhueta (um turbofan: diâmetro do fan 2,85 m, comprimento 4,9 m, diâmetro máximo da nacelle 3,44 m).
- A lista de peças em ordem de montagem, cada uma com seu material. Mire em 15 a 40 peças nomeadas; peças repetidas (pás, dentes, parafusos, bobinas) contam individualmente.
- A física que a faz funcionar, como 3 a 6 equações que você realmente computará, com constantes reais e o ponto de operação (um turbofan: ciclo Brayton, decolagem a N1 100 %, OPR 42, T4 1.750 K, cerca de 330 kN).
- O número que interessa ao espectador: o herói (empuxo, torque, batidas por hora, fluxo, potência). Ele ganha um mostrador enorme serifado e uma barra fina.
- A entrada que um espectador quer controlar: um controle deslizante (acelerador, velocidade do vento, RPM, velocidade da bomba, tamanho da moagem).
- A quebra: a falha com a qual um engenheiro se preocupa e o que o resolvedor diz que acontece (pá do fan solta e a carga de desbalanceamento, flutuação de válvula acima da rotação máxima, bomba travada, sobrepressão). Isso deve ser uma consequência computada, não uma animação.
2. Construa a página a partir do template
Copie kit/template.html para <nome>.html. Ele tem o mapa de importação (pinned [email protected]), as fontes, um bloco marcado onde o kit vai, e as quatro seções que você preenche:
const { THREE, Lab, MAT, GEO, heatGlow, clamp, lerp, approach, fmt } = window.LabKit
const lab = new Lab({ prompt, no, title, sub, size, view, cut }) // 1. o lab
// 2. as peças lab.mesh(GEO..., MAT..., { name, pos, explode, xray, count })
// 3. o resolvedor lab.hero(...); lab.slider(...); lab.onTick((dt, lab) => { ... lab.setHero(...) })
// 4. quebrar, explicar, filmar lab.breakIt(...); lab.how(...); lab.autoFilm(...); lab.start()
Logo após copiar, execute node <diretório da skill>/scripts/inline.mjs <nome>.html: ele cola o kit no bloco marcado para que a página seja um arquivo auto-contido onde quer que esteja (o src="../kit/lab-kit.js" do template só resolve dentro deste repositório). Em seguida, escreva sua máquina no segundo bloco de script.
3. Geometria: sólidos reais em tamanho real
Trabalhe em metros no próprio quadro da máquina, Y para cima, o chão em y = 0 a menos que você defina ground. Defina size para a maior dimensão real; o kit escala a exibição para que cada máquina se sente da mesma forma no cenário, e a barra de escala mostra o tamanho real.
- Peças redondas (eixos, discos, carcaças, bicos, cones, spinners, pistões, mostradores):
GEO.lathe([[r, y], ...])com um perfil FECHADO. Paredes:GEO.shell(perfil, espessura), tubos:GEO.tube(rExt, rInt, h), discos chanfrados:GEO.disc(r, h). Os cantos permanecem nítidos e as curvas sombreadas suavemente automaticamente. - Pás e palhetas:
GEO.rotor({ count, axis, r0, r1, chord, thick, camber, twist, pitch, sweep })constrói aerofólios reais curvados e torcidos (espessura NACA) como sólidos fechados e os anela. Use arrays[raiz, ponta]para chord, thick e camber. - Engrenagens:
GEO.gear({ teeth, module, width, bore, helix, spokes, rim }). Engrene duas engrenagens na distância central(z1 + z2) * module / 2e gire-as na razão inversa de dentes, defasadas por meio dente. - Tubos, mangueiras, fios:
GEO.pipe(pontos, r)(fechado, com tampas). Roteie-os ao longo da estrutura de porta a porta, nunca através de uma peça. - Fixadores:
GEO.bolts(n, R, tamanho, h)em cada flange. Molas:GEO.spring(R, fio, voltas, comprimento). Caixas:GEO.rbox(largura, altura, profundidade, r)(sempre arredondadas, nunca afiadas). Placas com furos:GEO.extrude(forma, profundidade). - Massas e inércias vêm da geometria:
GEO.volume(geo)fornece volume e centróide, multiplique pela densidade real.
Regras que mantêm tudo limpo:
- Cada peça é um sólido fechado (perfis de torno fechados, cascas com espessura, tubos com tampas). Isso é o que permite que o corte desenhe faces de seção sólidas. Superfícies abertas aparecem ocas quando cortadas.
- Nada intersecta visivelmente e nada flutua. Cada peça toca o que a segura (um flange assenta em uma face, um eixo corre em um rolamento, um poste alcança o chão). Verifique juntas em close ups.
- Detalhe para onde o olho vai: círculos de parafusos em flanges, chanfros, um lábio, uma placa de identificação, linhas de combustível, um chicote. Grandes áreas planas ganham uma emenda, uma linha de painel ou um acabamento de textura.
- Dê uma base à máquina: um suporte, berço, pedestal, bancada ou montagem com pés no chão. Máquinas raramente flutuam na vida real.
- Orçamento: até cerca de 700k triângulos e 200 malhas. Mescle peças estáticas repetidas com
GEO.merge/GEO.ring; mantenha grupos móveis separados.
4. Materiais: nunca um cinza só
Use predefinições MAT.*; elas carregam refletâncias medidas para que aço, titânio, alumínio, latão e cobre pareçam diferentes lado a lado. Cada predefinição aceita substituições (color, roughness, clearcoat, qualquer campo MeshPhysicalMaterial) e um finish (textura de micro rugosidade: turned anéis em peças torneadas, brushed estrias, cast manchas, smudge, knurl).
| Uso | Predefinição |
|---|---|
| eixos, discos, peças usinadas | MAT.steel, MAT.stainless, MAT.chrome |
| carcaças, fundidos | MAT.aluminium, MAT.castIron, MAT.steelDark |
| pás, aeroespacial | MAT.titanium, MAT.inconel (+ heatGlow) |
| conexões, fiação | MAT.brass, MAT.copper, MAT.gold |
| corpos pintados | MAT.paint({ color }), MAT.satin, MAT.anodised({ color }) |
| polímeros | MAT.plastic, MAT.rubber, MAT.carbon |
| janelas, cristais | MAT.glass, MAT.sapphire, MAT.ruby, MAT.enamel |
| luz, chama, gás quente | MAT.glow, heatGlow(material, kelvin) |
Escolha uma paleta como um designer industrial: principalmente metais e uma ou duas cores pintadas, no máximo um acento. Peças quentes brilham a partir da temperatura do resolvedor (material.userData.heat.value = T).
5. O resolvedor: números reais ou nada
Escreva uma pequena função pura a partir da entrada e do estado para cada número que você mostra, com unidades reais e constantes reais. Integre dinâmicas com approach (lag de primeira ordem: aceleração, massa térmica) ou rk4 (molas, escapes, pêndulos). Em seguida, acione o movimento a partir dela: uma RPM do resolvedor gira o eixo, um fluxo do resolvedor move as partículas, uma temperatura aquece o metal.
- Um herói:
lab.hero({ label, unit, max })e entãolab.setHero(valor, { state, sub, bad })a cada tick.statesão duas ou três palavras (acelerando, decolagem, fluxo estrangulado).subé uma linha com 2 ou 3 números adicionais. - Um controle deslizante:
lab.slider({ id, label, min, max, value, unit, ends }). Um segundo apenas se a máquina realmente precisar. - Etiquetas penduram em peças estáticas em pontos nos planos de seção:
lab.label(obj, 'Turbina AP', { at: [x, y, z], value: () => '12.979 rpm' }). lab.how(palavras, equações)preenche "Como é computado": o modelo em palavras simples e as equações como escritas no código. Diga o que foi simplificado.- Se um movimento for rápido demais para ver (um fan a 2.700 rpm), mostre-o em câmera lenta e diga isso em
how("rotação mostrada 1:60"). Nunca diminua os números. - Verifique a sanidade do ponto de operação contra a figura pública que você anotou na etapa 1. Se você estiver errado por mais de cerca de 20 %, corrija o modelo, não o número.
6. Fluxo, calor e efeitos
lab.flow({ paths, count, length, color, parent }): estrias que viajam ao longo de caminhos que você constrói a partir do caminho de fluxo real (ar através de um duto, sangue através de uma bomba, água através de um disco). Defina.speeda partir do resolvedor e.opacitya partir delab.state.cutpara que apareçam dentro do corte. Colora por uma quantidade computada (temperatura, pressão).lab.plume({ radius, length, dir, color: 'rocket' | 'jet', shocks }): um escapamento com diamantes de Mach; defina.powera partir do resolvedor.lab.sparks.emit(posMundo, n, velocidade)elab.shed(malha, v, w)para quebras: faíscas caem com gravidade e quicam; uma peça solta se torna um corpo rígido que pousa no chão.
7. Modos (o kit os faz; você os configura)
- Explodir: cada
lab.add/lab.meshrecebeexplode: [dx, dy, dz]no quadro do pai (metros). Mova peças ao longo de seu eixo de montagem, cascas externas mais longe e mantenha o núcleo no lugar. Nada deve cruzar nada no caminho para fora. - Corte:
cut: { a, b, center, reach }no Lab.aebsão as direções da região removida:a = [0,0,1], b = [0,1,0]remove o quarto em direção ao espectador e para cima (melhor para coisas com um eixo);b = aremove uma metade. Faces de seção são desenhadas automaticamente para cada sólido fechado, com uma hachura suave. - Raio-X:
xray: 'shell'em carcaças externas as transforma em vidro com bordas finas, para que o núcleo apareça enquanto funciona. - Câmera lenta, etiquetas, pausa vêm de graça (teclas S, L, Espaço). As partes interativas são órbita do mouse, o controle deslizante e os botões.
- Quebrar:
lab.breakIt({ label, run(lab), reset(lab) }).runmuda o estado do resolvedor (uma pá solta, uma válvula emperrada, uma vedação rompida) e o resolvedor computa a consequência. Mostre no herói (bad: true) e com faíscas, detritos ou trepidação.
8. Olhe como um crítico (obrigatório)
Renderize e LEIA cada imagem que você fizer. Use os scripts:
node scripts/shot.mjs <nome>.html out/review.png # o primeiro olhar
node scripts/shot.mjs <nome>.html out/cut.png --js "lab.toggle('cut', true); lab.toggle('labels', true)"
node scripts/shot.mjs <nome>.html out/near.png --js "lab.setView({ az: 70, el: 8, dist: 0.8, target: [x, y, z] })"
node scripts/shot.mjs <nome>.html out/film --film 1,4,8,12,17,22,26 # fotogramas do filme
Faça pelo menos quatro rodadas de revisão. Em cada uma: vista completa, corte com etiquetas, explodida, dois close ups de juntas e os fotogramas do filme. Compare com a fotografia de produto real da máquina em sua memória: proporções, contagem de peças, materiais, como a luz incide sobre ela. Liste o que está errado, corrija, renderize novamente. Pare apenas quando a lista estiver vazia. O script de captura imprime fps, contagem de peças e triângulos; mantenha as taxas de quadros interativas acima de 30.
9. O filme
lab.autoFilm({ runBeat, runSub, breakBeat, breakSub, sliderTo }) escreve a história padrão de 28 segundos a partir de sua máquina, em batidas numeradas com as legendas editoriais:
- Uma frase é todo o resumo (a barra de prompt se digita sozinha).
- Claude constrói a máquina (peças voam em ordem de montagem enquanto o contador sobe: "84 de 3.597 peças").
- Ela funciona (um cursor arrasta o controle deslizante; o número herói sobe a partir do resolvedor).
- Corte-a aberta (tampas de seção, etiquetas com valores ao vivo).
- Desmonte-a (explodir).
- Quebre-a (o cursor clica no botão de quebra; o resolvedor decide o que falha).
Ele faz loop: a última chave de câmera retorna à primeira. Para um filme personalizado, use lab.film('nome', { len, assemble, shots, events }): shots são chaves de câmera { t, az, el, dist, target, fov }, eventos são { t, beat: ['07', 'Frase em negrito.', 'Frase em cinza.'], set: { cut: 1 }, slider: { id, to, dur }, cursor: { to: 'slider:id:0.8' | 'button:break' | [x, y], click: true }, do(lab) {} }.
Grave (precisa de Node 18+, Playwright com Chromium, ffmpeg):
node scripts/record.mjs <nome>.html out/<nome>.mp4 --music freepd:Classical/Easy_Lemon
node scripts/record.mjs <nome>.html out/<nome>-portrait.mp4 --w 1080 --h 1350
A página executa no modo filme (?film=1): seu relógio só avança quando o gravador o avança, então cada quadro está completo e o filme é idêntico a cada take. O gravador protege cada captura de tela contra os quadros magenta que uma GPU headless travada pode retornar e digitaliza o filme finalizado; ele sai com código não zero se algum quadro estiver rosa. Música do FreePD é CC0; mesmo assim, credite a faixa.
Texto na tela
A página é editorial, não um painel: uma barra de prompt, um título serifado com um subtítulo itálico, um número enorme com unidades em itálico e uma barra fina, uma linha de números de suporte, um controle deslizante. Escreva como uma boa legenda: curta, concreta, sem exageros, unidades reais com um espaço (338 kN, 1.750 K, 4,2 L/min), milhares separados. As legendas das batidas são uma frase em negrito e uma frase em cinza.
O que dizer ao entregar
Dê o caminho do arquivo HTML, o comando do filme, o ponto de operação que o resolvedor atinge em relação à figura pública e qualquer coisa que você simplificou. Ofereça a próxima máquina.