180 lines
10 KiB
Markdown
180 lines
10 KiB
Markdown
|
|
# 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 | les sommets sont liés à l'os `head` ; une coiffure mal placée flotte ou traverse le crâne |
|
|||
|
|
| 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/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) :
|
|||
|
|
|
|||
|
|
```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
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
& $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 :
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
& $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.
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
& $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
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
& $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 |
|
|||
|
|
|
|||
|
|
## 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** : non gérées (coiffure rigide sur la tête).
|
|||
|
|
- **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.
|
|||
|
|
|
|||
|
|
## 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.
|