Tissu généré par programme (sans simulation)
Source : room-at-dawn (MIT), src/scene/parts/bed.js pour les couettes, couvertures, oreillers.
Ce dépôt extrait le code en une bibliothèque réutilisable, accompagnée d'un exemple consultable par étapes.
Idée centrale : le tissu n'est pas « simulé », mais « conçu ».
Sur un plan de coordonnées, on définit « de combien chaque point du tissu est plus haut que son support », puis on plaque ce plan sur le support.
Avantages : chaque étape est contrôlable, reproductible (même résultat pour une même graine), construit en moins de 0,5 seconde,
et d'autres objets (livre, téléphone, autre couverture) peuvent interroger la même fonction de hauteur pour être placés précisément sur le tissu.
Inconvénient : le tissu est statique – il ne réagit pas aux personnages (pour l'interactivité, voir references/engines.md).
Fichiers
| Chemin | Contenu |
|---|---|
scripts/cloth.js | Bibliothèque (ES module, dépend seulement de three) : RNG/bruit, Champ, Bosses, Famille de plis, Rides, Drapage sur support, Repli de coin, Grille, Aplatissement UV, Matériau de rides, Motif imprimé, Matériau coton, exportableMesh (conversion avant export GLB) |
example/index.html + main.js | Une couette non faite sur un lit, ?stage=1..5 ajoute progressivement chaque effet |
scripts/curtain.js | Rideaux : curtainPanel (intégration de profil sans allongement), auditPanel, linenTextures (lin toile), curtainMaterial (coutures, ourlets, plis de rangement, translucidité en contre-jour, micro-oscillation), curtainRing |
example/curtain.html | Une paire de rideaux devant une fenêtre, ?cam= (front, angle, top, hem, stitch, above), ?tied=1, ?fullness=, ?loops=, ?tex=checker |
example/preview-*.jpg | Images finales et par étape de l'exemple (preview-curtain.jpg pour les rideaux) |
references/shape.md | Conception du champ de hauteur : bosses, longs plis, adoucissement des crêtes, rides, zones plates |
references/drape-curl.md | Supports, affaissement, distorsion du plan, repli de coin, ourlets, objets posés sur le tissu, superposition d'une deuxième couche |
references/uv-material.md | Aplatissement UV, carte normale de micro-rides + cavity, motif imprimé, matériau |
references/verification.md | Données à vérifier, angles de caméra, symptômes courants et solutions |
references/curtain.md | Rideaux : intégration de profil et résolution de largeur, composition de θ(s), matériau, paramètres, vérification, problèmes rencontrés |
references/engines.md | Portage vers Godot/Unreal : export GLB, réécriture en GDScript/C++, intégration de tissu interactif |
Exécuter l'exemple
cd <dossier de la compétence> && python3 -m http.server 5420 --bind 127.0.0.1
# Ouvrir http://127.0.0.1:5420/example/
(<dossier de la compétence> est le répertoire de base affiché lors du chargement de cette compétence ; lorsqu'elle est installée comme plugin, elle se trouve sous ~/.claude/plugins/cache/)
Paramètres d'URL :
stage=1..5: respectivement bosses, ajout de longs plis, adoucissement des crêtes, rides, repli de coin et affaissement.cam=wide|close|top|side|left|foot: caméra par défaut.tex=checker: motif damier de 10 cm pour vérifier l'étirement UV.relax=0: désactive l'aplatissement UV pour comparaison.ui=0: cache le panneau de données pour les captures d'écran.
Une fois terminé, window.__cloth contient les données de vérification, et body[data-ready="1"] indique que la capture d'écran est possible.
Le bouton « Télécharger GLB » permet d'exporter le tissu vers d'autres moteurs.
Processus
| Étape | Action | Pourquoi | Bibliothèque |
|---|---|---|---|
| 1 | Définir le contour (quadrilatère) dans le plan et la « distance à l'ourlet » | Ourlet, fondu des rides, repli de coin | quadEdge |
| 2 | Bosses : 5 à 10 ellipses placées manuellement, chacune avec hauteur et angle, reliées par smooth-max | La forme générale détermine « l'état de la couette » – impossible avec du bruit | makeLobes lobesAt |
| 3 | Plis longs : 2–3 groupes de bruit billow directionnel, changeant de direction selon la zone | Les plis d'une couette suivent la direction de la tension | foldFamily |
| 4 | Ondulations verticales dans les parties retombantes ; déformation globale du domaine ; limite haute par soft cap | Le tissu qui pend n'est pas plat ; éviter les lignes trop droites ; crête maximale raisonnable | softCap |
| 5 | Adoucissement des crêtes : chaque point ne dépasse pas d'environ 1,2 cm la moyenne floutée deux fois, les creux restent nets | Un tissu rembourré n'a pas de pics – cela transforme une « montagne » en « couette » | Field.erodePeaks |
| 6 | Rides tracées une par une : à partir de points de pincement, elles rayonnent en éventail, sinon réparties selon le champ de tension, atténuées près des zones plates et des ourlets | Le bruit produit des rides marbrées, alors que les vraies rides sont des segments en forme de tente | CreaseSet crease |
| 7 | Ourlet : bande plate, rainure de couture, fronce | Les bords sont de vraies géométries pour être crédibles en gros plan | Exemple hemElev |
| 8 | Plaquage sur support : zone plate + arrondi + chute verticale | Un seul plan peut représenter à la fois le dessus du lit et le bord | boxSupport |
| 9 | Affaissement des plis hauts d'un côté : la distance d'affaissement dépend de la hauteur locale | Une bosse devient asymétrique (un côté raide, l'autre doux), pas un dôme symétrique | Exemple place |
| 10 | Repli de coin : la partie qui dépasse de la ligne de pli s'enroule d'abord en cylindre, puis se couche à plat sur la couette ; la zone écrasée est marquée comme plate | Ajoute un détail narratif | curl |
| 11 | Aplatissement UV sur la surface 3D (multi-grille, contrainte de longueur d'arête) | Les motifs imprimés ne s'étirent pas sur les plis abrupts | relaxUV uvStretch |
| 12 | Matériau : carte normale de micro-rides répétable (alpha = cavity) + motif imprimé + sheen | La géométrie gère le centimètre, la texture gère le millimètre | wrinkleTexture sprigPrintTexture cottonMaterial |
Règles à respecter impérativement
- L'aléatoire utilise impérativement
RNG(seed)/pn(...,seed), pasMath.random(). Les captures d'écran, le baking d'éclairage et la synchronisation multi-utilisateur en dépendent. - Les grandes formes sont échantillonnées par interpolation cubique (
Field.cubic), les rides par bilinéaire (Field.bil). Si les grandes formes utilisaient la bilinéaire, on verrait des facettes de 5 mm sur la grille. - Les rides ne doivent pas être générées par bruit. Le bruit produit des amas ; les vraies rides sont des lignes directionnelles qui s'affinent à leurs extrémités.
- Adoucir les crêtes d'abord, ajouter les rides ensuite. Si l'ordre est inversé, les arêtes des rides sont également adoucies.
- La zone plate sous un coin replié doit couvrir toute la région du pli (l'exemple utilise
QMAXpour le calcul automatique). Sinon, le coin replié repose sur des bosses et le motif s'étire en bandes (problème réel, voirreferences/verification.md). - L'aplatissement UV utilise la forme « non repliée » U ; l'étirement du coin replié est vérifié séparément.
relaxUVexige que le nombre de divisions soit un multiple de 8. - Le tissu retombant ne doit pas entrer en collision avec des objets en dessous : dans l'exemple, le cadre du lit est plus étroit que le matelas. Les collisions hors support ne sont pas gérées par cette méthode.
- Quand deux bords adjacents tombent simultanément, le coin nécessite une pièce triangulaire ou conique ;
boxSupportne le gère pas. Limitez-vous à deux bords opposés.
Valeurs initiales (testées dans l'exemple)
- Épaisseur à plat de la couette : 5 cm, hauteur des bosses multipliée par
LOBE_SCALE(0,3 pour une couette normalement utilisée, 1 pour une grosse bosse), limite haute soft cap 23 cm. - Espacement des plis longs : environ 12 cm, longueur environ 60 cm, amplitude 3–4 cm ; rayon d'adoucissement 5 unités (2,5 cm), limite 1,2 cm.
- Largeur des rides : 2,4–4 cm, hauteur environ 0,16–0,3 fois la largeur, 30 % encoches ; 4–7 rides par point de pincement, 200 réparties ailleurs.
- Grille : environ 7 mm (288×192), environ 130 000 triangles, modélisation en environ 0,45 s (dont 0,15 s pour l'aplatissement UV), 0 interpénétration, étirement UV p5/p95 environ 0,92/1,08.
Rideaux (tissu suspendu)
La méthode pour les couettes (« champ de hauteur plaqué sur support ») ne s'applique pas aux rideaux. Pour les rideaux : chaque section horizontale est une ligne de longueur fixe,
dessinée en intégrant l'angle de progression θ(s) le long du tissu, puis on ajuste le facteur multiplicatif de θ par dichotomie pour que cette colonne ait exactement la largeur souhaitée à cette hauteur.
Le tissu ne s'allonge pas, donc les UV sont en mètres et les motifs ne se déforment pas. Détails dans 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 doit être 0 ; stretchP95Pct doit être inférieur à 1
- Testé : un panneau d'environ 100 000 triangles, construit en 0,2 s, étirement p95 de 0,4–0,7 %, 0 croisement.
- Piège : si
depthest trop serré, le tissu perd 5–15 % de largeur. Réduisezfullness, ne compressez pas la profondeur. - Piège : si l'ourlet est trop étroit, les plis se croisent – le seuil dépend de la graine (dans l'exemple, le panneau droit a encore des croisements à environ 0,67x, mais pas à 0,79x). Surveillez
crossings, changez de graine si nécessaire. - Par défaut,
depth[-0.11, 0.16] ne raccourcit pas le tissu, mais la tringle doit être à environ 12 cm du mur.