LifePlay-Revival/Docs/Migration/13_Protocole_Coiffure.md
edujiro5972 ac7de7d2c2 SKIN : coiffures liees au corps par transfert de poids et sorties de la peau
Les meches longues suivent cou, clavicules et poitrine au lieu de tourner avec la tete ;
6 coiffures Pocolov reconstruites (-Rebuild).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:36:28 +02:00

15 KiB
Raw Blame History

13. Protocole de conversion d'une coiffure

Ce protocole décrit comment ajouter au jeu une coiffure livrée en maillage statique (FBX de Fab ou d'ailleurs), sans modifier aucun Blueprint. Il a été établi sur Pocolov Hair 17 (lot O7e, 11_Audit_Optimisation.md §16.8) puis rejoué de bout en bout avec les outils ci-dessous : résultat identique au millimètre.

Durée : environ 30 minutes pour une coiffure, contrôles en jeu compris.

1. Ce que le jeu attend d'une coiffure

Exigence Raison
SkeletalMesh dont les os portent les noms Genesis 8 (hip, pelvis… neckUpper, head) Person fait suivre la coiffure au corps par SetLeaderPoseComponent, qui associe les os par leur nom
Placée autour de la tête de Bridget, dans la pose de référence une coiffure mal placée flotte ou traverse le crâne
Poids de peau répartis sur tête, cou, clavicules et poitrine une coiffure longue liée à la seule tête tourne d'un bloc avec elle et ses mèches traversent épaules et poitrine
Matériaux enfants de /Game/Heavy/Daz/Bridget/Hairs/DazHair le jeu règle la couleur et l'épaisseur par les paramètres HairColor et HairThickness
Déclarée dans un fichier Modules/<module>/**/*.lphair la liste des coiffures du jeu est construite depuis ces fichiers (lots H1, H2) ; un maillage non déclaré n'est jamais utilisé
Nom d'objet unique les personnages désignent leur coiffure par ce nom (HAIR Hairstyle: <nom> dans les .lpcharacter)

Coiffures exclues : les « grooms » MetaHuman (liés à la tête MetaHuman ; plugin HairStrands limité à l'éditeur depuis O1). Une coiffure déjà riggée Genesis 8 (export Daz) n'a pas besoin des étapes 2 et 3 : l'importer en SkeletalMesh et passer à l'étape 4.

2. Outils

Outil Rôle
Tools/HairImportFbx.py import du FBX en maillages statiques séparés, dans un dossier de travail ; affiche tailles et emplacements de matériaux
commandlet LPHairFromStaticMesh (Source/LifePlayEditorTools) ajuste la coiffure sur la tête de Bridget et la convertit en SkeletalMesh Genesis 8
Tools/HairMaterials.py importe les textures, crée les matériaux <Nom>_Cap et <Nom>_Strands, les affecte, contrôle les dépendances
Tools/HairPipeline.ps1, Tools/FbxMaterialMap.py chaîne industrialisée d'un lot de coiffures (§7)
Tools/BuildCollections.py range la coiffure dans la collection LifePlay_Cheveux de l'éditeur
option de jeu -LPVerifyHairstyles journalise la construction de la liste des coiffures

Variables utilisées ci-dessous (PowerShell) :

$UE = 'D:\Game\Launcher\Engine\UE_5.5\Engine\Binaries\Win64\UnrealEditor-Cmd.exe'
$P  = 'D:\Game\LifePlay-master 5.5\LifePlay.uproject'
$T  = 'D:/Game/LifePlay-master 5.5/Tools'
$W  = 'D:/Game/LifePlay_Backup_5.5/<lot>/src'     # sources de travail, chemins SANS espaces

3. Étapes

Étape 0 : préparation

  1. Vérifier la licence du produit (page Fab : « License terms »). CC BY impose une attribution ; noter auteur, titre, lien.
  2. Télécharger l'archive (accord de l'utilisateur), la copier dans D:\Game\LifePlay_Backup_5.5\<lot>\.
  3. Extraire ; repérer le FBX et les textures. Copier dans $W sous des noms sans espaces (les arguments des scripts Python sont séparés par des espaces) : hair.fbx, diffuse.png, strands_opacity.jpg…
  4. Identifier les textures en les ouvrant :
    • couleur des mèches : de préférence grise (elle est teintée par HairColor) ;
    • masque des mèches : blanc = visible, noir = transparent, en bandes verticales ;
    • masque de la calotte (lisière) : facultatif, voir étape 4.
  5. Tag git <lot>-avant. Choisir le nom de la coiffure (unique, sans espace, ex. Pocolov17) et son dossier : /Game/Heavy/New5/Hairs/ (hors des dossiers à chemin fixe, 08_Guide_Developpeur.md §2.1).

Étape 1 : import

& $UE $P -run=pythonscript "-script=$T/HairImportFbx.py fbx=$W/hair.fbx dest=/Game/Heavy/New5/Hairs/_Work" -unattended -nopause -nosplash

Lire les lignes HAIRIMPORT : repérer le maillage de la coiffure et la tête de référence souvent livrée avec (ex. Pocolov : Hair_17, 8 250 triangles, emplacements Hair_Base, Hair_01 ; Head, 21 262 triangles). Noter quel emplacement est la calotte (ici Hair_Base). Sans tête de référence, voir §5.

Étape 2 : ajustement et conversion

Essai à blanc d'abord :

& $UE $P -run=LPHairFromStaticMesh '-Static=/Game/Heavy/New5/Hairs/_Work/Hair_17' '-FitHead=/Game/Heavy/New5/Hairs/_Work/Head' '-Out=/Game/Heavy/New5/Hairs/<Nom>' -DryRun -unattended -nopause -nosplash

Contrôler les lignes LogLPHairFromStatic :

Ligne Attendu
Tete du corps Bridget : haut du crâne ≈ 15 × 20 cm
Tete de reference haut du crâne du même ordre
Ajustement : echelle entre 0,8 et 1,5 sur chaque axe ; un écart fort entre X et Y signale une tête de référence atypique
Os 'head' correction aucune (squelette cible identique au corps)
Coiffure placee largeur ≈ 25 à 32 cm (Flora : 31 cm), sommet ≈ 181-183 cm

Puis sans -DryRun. La commandlet refuse d'écraser un asset existant : pour refaire, déplacer d'abord <Nom> et <Nom>_Skeleton vers la sauvegarde.

Liaison au squelette (-Skin, défaut transfer) : chaque sommet de la coiffure reçoit les poids des 6 sommets du corps les plus proches (-Neighbors), moyennés selon la distance, 4 influences au plus ; les os des bras et des jambes sont ramenés à leur ancêtre (une mèche ne suit pas un bras). Tout sommet à moins de 3 mm de la peau, ou dessous, est repoussé le long de la normale du corps (-Gap, en cm). Résultat type (Pocolov 06) : tête 61 %, haut de la poitrine 10 %, clavicules 14 %, cou 4 %, pectoraux 3 % ; 660 sommets sur 5 618 sortis de la peau. -Skin=rigid : tout sur l'os head (première version, à réserver aux coiffures courtes).

Paramètres de retouche (après un premier contrôle en jeu) : -OffsetZ= (cm, monter/descendre), -OffsetY= (cm, avancer/reculer), -Scale= (facteur global), -Margin= (défaut 1,05 : écart calotte/cuir chevelu), -Cranium= (défaut 0,3 : hauteur mesurée sous le sommet, en fraction de la profondeur de la tête), -Uniform (même échelle sur X et Y).

Étape 3 : textures et matériaux

& $UE $P -run=pythonscript "-script=$T/HairMaterials.py mesh=/Game/Heavy/New5/Hairs/<Nom> diffuse=$W/diffuse.png strands_opacity=$W/strands_opacity.jpg cap_opacity=white cap=Hair_Base thicken=1" -unattended -nopause -nosplash
  • cap= : emplacements de la calotte (séparés par des virgules) ; tous les autres reçoivent le matériau des mèches.
  • cap_opacity=white : calotte opaque (recommandé : une lisière découpée laisse voir le crâne entre les mèches) ; sinon le fichier du masque de la calotte.
  • thicken= : épaississement du masque des mèches. 1 pour un masque large (cartes de mèches, Pocolov) ; 10 pour un masque de mèches fines (coiffures Daz). Une valeur trop forte donne des cartes opaques.

Contrôle : la dernière ligne HAIRMAT dependances … -> OK (la coiffure ne dépend que de son squelette et de ses deux matériaux).

Étape 4 : nettoyage

Déplacer Content/Heavy/New5/Hairs/_Work vers D:\Game\LifePlay_Backup_5.5\<lot>\ (il ne doit pas être cuit dans le jeu). Ne rien supprimer sans copie.

Étape 5 : déclaration

Fichier Content/Modules/<module>/Hairstyles/<nom>.lphair (module existant, ex. lp_Revival, ou module du mod) :

// <Titre> - <auteur> - licence <licence>
// Source : <lien>
// Modifications : rattachee au squelette Genesis 8 (os head), ajustee a la tete de Bridget, materiaux DazHair.
HAIRSTYLE: /Game/Heavy/New5/Hairs/<Nom>.<Nom>
SEX: F
DAZ: true

Licence à attribution : ajouter la même mention dans Licenses/Free_3D_Models_Credits.txt.

Étape 6 : collections, build, contrôle du journal

& $UE $P -run=pythonscript "-script=$T/BuildCollections.py" -unattended -nopause -nosplash

Build Development (09_Commandes_Utiles.md §2) dans un nouveau dossier d'archive (la mise en place avec -iterate ne retire pas les fichiers supprimés). Lancer le jeu ; le journal doit contenir :

LogLifePlay: Coiffures : <Nom> ajoutee (index N, F, module <module>)

Étape 7 : contrôle en jeu (utilisateur)

# Contrôle Défaut typique → correction
1 Création de personnage du bon sexe : la coiffure est en fin de liste absente : chemin du .lphair, module désactivé, journal
2 De face : le crâne est couvert zones chauves, coiffure étroite : vérifier l'ajustement (§4), -Scale, -Margin
3 De profil : rien ne traverse le crâne, l'oreille, les épaules ; pas de trou au-dessus de l'oreille trous : cap_opacity=white ; trop haute/basse : -OffsetZ ; trop en avant/arrière : -OffsetY
4 Couleur et épaisseur réglables dans le menu sans effet : matériau non DazHair
5 Mouvement (marche, animation) : la coiffure suit la tête décalée : os head absent ou correction de pose non nulle
6 Nouvelle partie (liste des villes) et Continue —

Puis : entrée CHG dans Journal_Modifications.md, commit, tags <lot>-apres / <lot>-valide.

4. Pièges rencontrés (O7e)

Piège Effet Règle
Ajuster sur la tête entière la tête Pocolov a des oreilles très larges (24,4 cm) : coiffure rétrécie à 74 %, enfoncée dans le crâne ajuster sur le haut du crâne (option -Cranium, par défaut)
Thicken des coiffures Daz (10) sur un masque large mèches en cartes noires opaques thicken=1 pour les cartes de mèches
Lisière découpée de la calotte crâne visible au-dessus de l'oreille cap_opacity=white
Affectation des matériaux en Python save_loaded_asset ne sauve que les assets « modifiés » ; une affectation par propriété ne les marque pas sauvegarder avec only_if_is_dirty=False (fait par HairMaterials.py)
Matériaux importés du FBX souvent sans texture reliée ne pas importer les matériaux (HairImportFbx.py) ; recréer avec HairMaterials.py
Comparer des noms d'assets soldier et Soldier désignent le même asset comparaisons insensibles à la casse
Liaison rigide à la tête (première version) cheveux longs : les mèches tournent avec la tête et traversent épaules et poitrine (vidéo utilisateur) transfert de poids depuis le corps et sortie de la peau (-Skin=transfer, défaut)

5. Cas particuliers

  • Pas de tête de référence dans le FBX : utiliser la coiffure elle-même comme -FitHead (son haut est la calotte), avec -Margin=1.0, puis corriger en jeu avec -Scale et -OffsetZ.
  • Coiffure masculine : SEX: M dans le .lphair (le menu du personnage masculin la propose).
  • Morphs de forme : non générés (la coiffure ne suit pas les morphs du visage). Un morph existant de la coiffure peut être déclaré avec FIT_MORPH: <morph> <valeur>.
  • Mèches animées : pas de simulation physique ; les mèches suivent tête, cou et poitrine par leurs poids.
  • Morphs du corps : la sortie de la peau est calculée sur le corps de base ; une poitrine ou des épaules agrandies par les morphs peuvent encore traverser les mèches les plus proches.
  • Coiffure apportée par un mod sans recompiler le jeu : impossible aujourd'hui (le maillage doit être cuit avec le jeu) ; étape H3 prévue.

7. Chaîne industrialisée (Tools/HairPipeline.ps1)

Les étapes 0 à 6 sont enchaînées pour un lot de coiffures décrit par un fichier JSON (Tools/hairs/<lot>.json) :

{ "module": "lp_Revival", "folder": "/Game/Heavy/New5/Hairs", "backup": "D:/Game/LifePlay_Backup_5.5/<lot>",
  "hairs": [ { "name": "Pocolov15", "archive": "D:/Game/pocolov-hair-15.zip", "title": "Pocolov Hair 15",
               "author": "...", "license": "CC BY 4.0", "url": "https://www.fab.com/listings/...", "sex": "F",
               "mesh": "auto", "head": "auto", "cap_slots": "auto", "diffuse": "auto", "strands_opacity": "auto",
               "cap_opacity": "white", "thicken": 1 } ] }

Options par coiffure : margin, scale, offset_z, offset_y, skin, gap (transmises à LPHairFromStaticMesh). -Rebuild refait une coiffure déjà convertie (la version précédente est déplacée dans <backup>\<nom>\precedente_<date>).

.\Tools\HairPipeline.ps1 -Config Tools\hairs\<lot>.json -Step Inspect      # puis relire <backup>\rapport_Inspect.txt
.\Tools\HairPipeline.ps1 -Config Tools\hairs\<lot>.json -Step Apply        # [-Only <nom>] pour une seule coiffure

Inspect : extraction (zip, rar, 7z, archives imbriquées, avec 7-Zip), copie du FBX et des textures sous des noms sans espaces, import (HairImportFbx.py), lecture des associations matériau → textures du FBX (Tools/FbxMaterialMap.py, lecteur de FBX binaire sans SDK), puis détection des champs auto :

Champ Règle
mesh plus gros maillage qui n'est pas la tête (nom quelconque : Box001 pour Pocolov 03)
head maillage dont le nom contient head ; sinon la coiffure elle-même (et margin 1,0)
cap_slots emplacements nommés base, cap ou scalp, seulement s'il reste un autre emplacement pour les mèches
diffuse parmi les textures nommées hair (si l'archive contient une tête complète : peau, yeux…) : non masque, grise de préférence, la plus grande
strands_opacity masque (gris, noir/blanc) vertical (un masque carré est la lisière de la calotte) ; préférence au nom d'un emplacement des mèches, puis aux bords latéraux sombres (carte à bords transparents) ; emplacement unique : masque déclaré par le FBX

Les champs détectés sont mémorisés dans auto_fields et recalculés à chaque inspection ; une valeur saisie à la main n'est jamais écrasée. Le rapport liste chaque texture (taille, saturation, part noir/blanc, bas et bords sombres) et les associations du FBX.

Apply : essai à blanc et contrôle des échelles (entre 0,6 et 1,8, sinon la coiffure est sautée), conversion, matériaux (HairMaterials.py ; matériau de calotte créé seulement s'il sert), dossier de travail déplacé vers la sauvegarde, .lphair avec attribution, ligne de crédits (sans doublon), collections, bilan. Une coiffure dont le SkeletalMesh existe déjà est sautée : la chaîne peut être relancée après une interruption.

Premier lot (HAIRS1, 2026-10-02) : Pocolov Hair 03, 06, 11, 15, 16 (CC BY 4.0). Cas rencontrés et intégrés aux règles : modèle dans un RAR (03) ; archive avec tête complète, textures de peau et d'yeux (03) ; maillage nommé Box001 (03) ; masque carré pris pour celui des mèches (16) ; emplacement unique (11) ; masques A/A1 voisins (03, 15). Résultat : 5 coiffures conformes (dépendances limitées au squelette et aux matériaux), toutes ajoutées par le jeu.

Licences : seules les licences permettant la redistribution (CC BY, CC0) conviennent, l'archive des sources publiée contenant Content/Heavy. La licence standard Fab (« personal/professional ») ne le permet pas.

6. Retour arrière

Retirer le fichier .lphair suffit à retirer la coiffure du jeu. Pour retirer aussi les assets : déplacer Content/Heavy/New5/Hairs/<Nom>* vers la sauvegarde, régénérer les collections, reconstruire.