Tecidos Programados (sem simulação)
Fonte: room-at-dawn (MIT), src/scene/parts/bed.js (edredom, cobertor, travesseiro).
Aqui foi extraído para uma biblioteca reutilizável, com um exemplo que pode ser visualizado em etapas.
Ideia central: o tecido não é "simulado", é "projetado".
Em coordenadas planas, define-se "o quanto cada ponto do tecido está mais alto que o suporte" e depois mapeia-se esse plano sobre o suporte.
As vantagens são: cada passo é controlável e reproduzível (mesma semente sempre gera o mesmo resultado), a construção leva menos de 0,5 segundos,
e outros objetos (livros, celular, outro cobertor) podem consultar a mesma função de altura, garantindo que fiquem sobre o tecido.
A desvantagem é que o tecido é estático: não é empurrado por personagens (para interação, veja references/engines.md).
Arquivos
| Caminho | Conteúdo |
|---|---|
scripts/cloth.js | Biblioteca (ES module, depende apenas de three): RNG/ruído, Field, lobos, famílias de dobras, vincos, draping sobre suporte, virada de cantos, malha, relaxamento UV, textura de rugas, estampa, material de algodão, exportableMesh (conversão antes de exportar GLB) |
example/index.html + main.js | Um edredom desarrumado sobre uma cama, ?stage=1..5 para adicionar cada efeito progressivamente |
scripts/curtain.js | Cortina: curtainPanel (integração de seção transversal sem esticar), auditPanel, linenTextures (linho liso), curtainMaterial (bainhas, costuras, rugas de armazenamento, translucidez contraluz, micro-ondulação), curtainRing |
example/curtain.html | Um par de cortinas penduradas em frente a uma janela, ?cam= (front, angle, top, hem, stitch, above), ?tied=1, ?fullness=, ?loops=, ?tex=checker |
example/preview-*.jpg | Imagens de exemplo concluídas e de cada etapa (preview-curtain.jpg é a cortina) |
references/shape.md | Design do campo de altura: lobos, dobras longas, aplainamento de picos, vincos, regiões planas |
references/drape-curl.md | Suporte, tombamento, distorção planar, virada de cantos, bainhas, colocar objetos sobre o tecido, sobrepor segunda camada |
references/uv-material.md | Relaxamento UV, mapa normal de rugas finas + cavidade, estampa, material |
references/verification.md | Quais dados verificar, quais ângulos de câmera, tabela de sintomas comuns |
references/curtain.md | Cortinas: integração de seção transversal e solução de largura, composição de θ(s), material, parâmetros, verificação, problemas encontrados |
references/engines.md | Portabilidade para Godot/Unreal: exportar GLB, reescrever em GDScript/C++, como integrar tecidos interativos |
Executando o Exemplo
cd <pasta da skill> && python3 -m http.server 5420 --bind 127.0.0.1
# Abra http://127.0.0.1:5420/example/
(<pasta da skill> é o diretório base exibido ao carregar esta skill; quando instalado como plugin, fica em ~/.claude/plugins/cache/)
Parâmetros de URL:
stage=1..5: respectivamente, lobos, adicionar dobras longas, adicionar aplainamento de picos, adicionar vincos, adicionar virada de cantos e tombamento.cam=wide|close|top|side|left|foot: câmera padrão.tex=checker: substitui por um grid de 10 cm para verificar estiramento UV.relax=0: desliga o relaxamento UV, para comparação.ui=0: esconde o painel de dados, útil para capturas de tela.
Após a conclusão, window.__cloth conterá os dados de verificação, e body[data-ready="1"] indica que a cena está pronta para captura.
O botão "Baixar GLB" permite exportar o tecido para uso em outros motores.
Fluxo
| Etapa | O que faz | Por quê | Biblioteca |
|---|---|---|---|
| 1 | Define o contorno (quadrilátero) e a "distância até a bainha" em coordenadas planas | Bainhas, desaparecimento de vincos, virada de cantos precisam disso | quadEdge |
| 2 | Lobos: posiciona manualmente 5–10 elipses, cada uma com altura e orientação, combinadas com smooth-max | A forma geral determina "em que estado o edredom está"; ruído não consegue fazer isso | makeLobes lobesAt |
| 3 | Dobras longas: 2–3 grupos de ruído billow direcional, alternando direção conforme a região | As dobras do edredom seguem a direção em que ele é esticado | foldFamily |
| 4 | Faz ondas longitudinais nas partes penduradas; domain warp global; soft cap limita a altura | Tecido pendurado não é plano; evita linhas retas artificiais; o lobo mais alto não deve ser exagerado | softCap |
| 5 | Aplainamento de picos: cada ponto pode ser no máximo ~1,2 cm mais alto que a vizinhança (após duas borradas), vales permanecem nítidos | Tecido com enchimento não tem picos; esta etapa transforma de "montanha" em "edredom" | Field.erodePeaks |
| 6 | Vincos traçados um a um: a partir de pontos de aperto, irradiam em leque; as demais áreas seguem o campo de tensão; atenuam perto de regiões planas e bainhas | Vincos feitos com ruído parecem mármore; precisam ser segmentos com perfil de "tenda" | CreaseSet crease |
| 7 | Bainha: faixa plana, sulco da costura, franzido | As bordas são geometria real, necessárias para verossimilhança em close | Exemplo hemElev |
| 8 | Draping sobre suporte: região plana + cantos arredondados + queda vertical | Um único plano pode representar tanto a parte sobre a cama quanto a parte pendurada | boxSupport |
| 9 | Tombamento de dobras altas: a distância do tombamento depende da altura local | As protuberâncias ficam com um lado íngreme e outro suave, em vez de simétricas como pães | Exemplo place |
| 10 | Virada de cantos: a parte que ultrapassa a linha de dobra é enrolada em um cilindro e depois achatada sobre o edredom; a área pressionada é marcada como plana | Adiciona um detalhe que conta uma história | curl |
| 11 | Relaxamento UV na superfície 3D (multigrid, restrições de comprimento de aresta) | Estampas em dobras íngremes não ficam esticadas | relaxUV uvStretch |
| 12 | Material: mapa normal de rugas finas repetível (alpha armazena cavidade) + estampa + sheen | A geometria lida com centímetros, a textura lida com milímetros | wrinkleTexture sprigPrintTexture cottonMaterial |
Regras Obrigatórias
- Aleatoriedade sempre via
RNG(semente)/pn(...,semente), nuncaMath.random(). Dependemos disso para regressão de capturas de tela, baking de iluminação e sincronização multiusuário. - Formas grandes usam interpolação cúbica (
Field.cubic), vincos usam bilinear (Field.bil). Se formas grandes usarem bilinear, a malha apresentará facetas de 5 mm. - Vincos não devem ser feitos com ruído. Ruído produz aglomerados; vincos reais são linhas direcionais que afinam nas pontas.
- Primeiro aplaina os picos, depois adiciona os vincos. Se a ordem for invertida, as cristas dos vincos também serão aplainadas.
- A região plana sob o canto virado deve cobrir toda a extensão da dobra (o exemplo usa
QMAXpara calcular automaticamente). Se não cobrir totalmente, a parte virada ficará sobre um lobo alto e a textura esticará em tiras (já ocorreu, vejareferences/verification.md). - O relaxamento UV usa a forma "não virada" U; o estiramento da parte virada deve ser verificado separadamente.
relaxUVexige que o número de divisões seja múltiplo de 8. - Tecido pendurado não pode colidir com objetos abaixo: o exemplo faz o estrado da cama mais estreito que o colchão. Colisões fora do suporte não são tratadas por este método.
- Quando dois lados adjacentes estão pendurados simultaneamente, o canto precisa de um formato cônico ou gusset;
boxSupportnão trata isso. Permita apenas que lados opostos fiquem pendurados.
Valores Iniciais (medidos no exemplo)
- Espessura do edredom deitado: 5 cm. Altura dos lobos ×
LOBE_SCALE(0,3 é sono normal, 1 é amontoado). Soft cap máximo: 23 cm. - Espaçamento entre dobras longas: ~12 cm, comprimento ~60 cm, amplitude 3–4 cm. Raio de aplainamento: 5 células (2,5 cm), limite 1,2 cm.
- Largura dos vincos: 2,4–4 cm, altura ~0,16–0,3 vezes a largura, 30% são sulcos. 4–7 vincos por ponto de aperto; 200 grupos espalhados.
- Malha: ~7 mm (288×192), ~130 mil triângulos. Modelagem: ~0,45 s (sendo ~0,15 s para relaxamento UV). Colisões: 0. Estiramento UV p5/p95: ~0,92/1,08.
Cortinas (tecidos pendurados)
O método do edredom é "campo de altura mapeado sobre suporte", não se aplica a cortinas. Para cortinas, adotamos: cada seção horizontal é um fio de comprimento fixo,
desenhado integrando o ângulo de curvatura θ(s) ao longo do tecido, e a largura desejada é obtida ajustando o fator de θ por bissecção.
O tecido não estica, então as UVs usam metros diretamente e a textura não deforma. Detalhes em references/curtain.md.
import { curtainPanel, auditPanel, linenTextures, curtainMaterial, curtainRing, CU } from './scripts/curtain.js';
const p = curtainPanel({ x0t: 0.27, x1t: 0.95, x0h: 0.25, x1h: 0.97, zc: 0.12, yTop: 2.29, yHem: 0.02, loops: 7, seed: 4101 });
const lin = linenTextures();
scene.add(new THREE.Mesh(p.geo, curtainMaterial({ map: lin.map, normalMap: lin.normalMap, yTop: 2.29 })));
console.log(auditPanel(p)); // crossings deve ser 0; stretchP95Pct deve ser menor que 1
- Medido no exemplo: um painel com ~100 mil triângulos, construído em 0,2 s, estiramento p95 de 0,4–0,7%, cruzamentos 0.
- Problema conhecido: se
depthfor muito apertado, o tecido perde 5–15% da largura. Se o espaço for insuficiente, reduzafullness, não force a profundidade. - Problema conhecido: se a bainha inferior for muito estreita, as dobras podem se cruzar; o limiar depende da semente (no exemplo, o painel direito ainda tinha cruzamentos em ~0,67x e só passou em 0,79x). Verifique
crossingse, se necessário, mude a semente. - O
depthpadrão [-0.11, 0.16] não encurta o tecido, mas a haste deve estar a ~12 cm da parede.