In dieser Anleitung erfahren Sie, wie Sie einen Groom für den Import aus Mayas älterem XGen-Haarkreationssystem einrichten, um ihn in Unreal Engine mit einem Satz unterstützter Attribute zu importieren, die in der Dokumentation Alembic für Grooms-Spezifikation beschrieben sind.
Für die Erstellung der Assets für diese Anleitung wurde Maya 2018.6 benutzt.
Konvertierung alter XGen-Beschreibungen
Konvertieren von Hilfslinien in NURBS-Kurven
Verwenden Sie die folgenden Schritte, um die Hilfslinien Ihres Groom in Kurven zu konvertieren und eine Reihe von Kurven zu speichern, die mit den Hilfslinien übereinstimmen, die Sie übertragen möchten.
-
Legen Sie Ihr Maya-Menü auf Modeling fest, damit Sie die korrekten Menü-Optionen sehen.
-
Klicken Sie im Menü auf die Dropdown-Liste Generate und wählen Sie XGen Editor aus.
-
Verwenden Sie im Fenster XGen den Tab Utilities aus, um Guides to Curves auszuwählen.
-
Klicken Sie auf Create Curves.
Nach der Fertigstellung sollte der Output von Groom in etwa so aussehen:
Konvertieren von Grooms in XGen Interactive Grooms
Wenn Sie die alte XGen-Beschreibung verwenden, muss der Groom in einen XGen Interactive Groom konvertiert werden. Sie können das folgendermaßen erreichen:
-
Wählen die XGen Description-Knoten aus.
-
Klicken Sie im Menüsatz Modeling im Hauptmenü auf die Dropdown-Liste Generate und wählen Sie anschließend Convert to Interactive Groom aus.
Spline-Beschreibungen in NURBS-Kurven exportieren
Befolgen Sie diese Schritte, um die ausgewählten Spline-Beschreibungen als Alembic-Datei zu exportieren, die Sie mit den interpolierten Haaren als NURBS-Kurven importieren können.
-
Wählen Sie Ihren XGen-Knoten „Spline Description“ aus. Klicken Sie dann im Menü Modeling auf die Dropdown-Liste Generate. Wählen Sie in der Liste Cache > Export Cache aus.
-
Legen Sie im Fenster Export Cache Folgendes fest:
- Cache Time Frame: Auf Current Frame festlegen
- Multiple Transforms: Deaktiviert
- Write Final Width: Aktiviert
-
Geben Sie einen Namen für Ihre Datei ein und wählen Sie Alembic als Dateityp aus.
- Klicken Sie auf Export.
-
Verwenden Sie das Menü File, um Import auszuwählen. Nun öffnet sich das Fenster Import, in dem Sie Ihre Alembic-Datei („.abc“) auswählen und in Ihre Szene importieren können.
Nach dem Import sollten Sie nun über eine XGen-Spline-Beschreibung verfügen, die exportiert und als Alembic-Datei gespeichert und importiert wurde, wodurch die interpolierten Haare als NURBS-Kurven importiert wurden.
Erstellen von Attributen
Gruppen-ID Attribute erstellen
Interpolierte Haare können in einer oder mehreren Gruppen exportiert werden. Diese Gruppen werden in Unreal Engine für die eindeutige Materialzuweisung erkannt.
Verwenden Sie das folgende Script bei der Erstellung von Gruppen-ID-Attributen:
from maya import cmds
attr_name = 'groom_group_id'
# HINWEIS: Ändern Sie die folgenden Namen, um die Szene Ihres Knotens widerzuspiegeln.
groups = ['hair_brows_splineDescription1|SplineGrp0', 'hair_lashes_splineDescription1|SplineGrp0', 'hair_head_splineDescription1|SplineGrp0']
for groom_group_id, group_name in enumerate(groups):
# Kurven unter xgGroom holen
curves = cmds.listRelatives(group_name, ad=True, type='nurbsCurve')
# Gruppe mit der Gruppen-ID taggen
cmds.addAttr(group_name, longName=attr_name, attributeType='short', defaultValue=groom_group_id, keyable=True)
# Attribut hinzufügen
# zwingt Mayas Alembic, Daten als GeometryScope::kConstantScope zu exportieren
cmds.addAttr(group_name, longName='{}_AbcGeomScope'.format(attr_name), dataType='string', keyable=True)
cmds.setAttr('{}.{}_AbcGeomScope'.format(group_name, attr_name), 'con', type='string')
Hilfslinienattribute erstellen
Wenn Sie die Hilfslinienattribute für Ihren Groom erstellen, werden nur die als Guide getaggten Kurven in Unreal Engine für die Simulation verwendet. Sind in der Alembic-Datei keine Hilfslinien spezifiziert, wird ein Prozentsatz der interpolierten Haare beim Importprozess in Unreal Engine intern als Hilfslinien getaggt.
Beim Importieren eines Groom ohne Hilfslinien können Sie den Prozentsatz der interpolierten Haare, die als Hilfslinien getaggt werden, mit den Groom Importoptionen festlegen. Standardmäßig werden nur 10 % der Anzahl der Haare als Hilfslinien verwendet.
Verwenden Sie das folgende Script, wenn Sie Ihre Hilfslinienattribute erstellen:
from maya import cmds
attr_name = 'groom_guide'
# Kurven unter xgGroom holen
curves = cmds.listRelatives('xgGroom', ad=True, type='nurbsCurve')
# neue Gruppe erstellen
guides_group = cmds.createNode('transform', name='guides')
# Gruppe als Groom_guide taggen
cmds.addAttr(guides_group, longName=attr_name, attributeType='short', defaultValue=1, keyable=True)
# zwingt Alembic von Maya, Kurven als eine Gruppe zu exportieren.
cmds.addAttr(guides_group, longName='riCurves', attributeType='bool', defaultValue=1, keyable=True)
# Attribut hinzufügen
# zwingt Mayas Alembic, Daten als GeometryScope::kConstantScope zu exportieren
cmds.addAttr(guides_group, longName='{}_AbcGeomScope'.format(attr_name), dataType='string', keyable=True)
cmds.setAttr('{}.{}_AbcGeomScope'.format(guides_group, attr_name), 'con', type='string')
# Parent-Kurven unter der Hilfsliniengruppe
for curve in curves:
cmds.parent(curve, guides_group, shape=True, relative=True)
Groom_Width-Attribut
In Maya hat der Breitenwert ein besonderes Verhalten, anders als bei anderen DCC-Anwendungen, die der Alembic für Grooms-Spezifikation folgen können, um diese abzurufen und zur Erstellung Ihres Grooms zu verwenden.
Maya kann die Breitenwerte direkt auf den Kurven exportieren, sodass Sie kein benutzerdefiniertes groom_width Attribut exportieren müssen. Der Importeur konvertiert diese Werte automatisch in das Attribut. Sollte das Attribut groom_wdith beim Import in Unreal Engine beim Groom vorhanden sein, wird es nicht überschrieben. Wenn groom_wdith nicht spezifiziert ist oder nicht aus Breitenwerten konvertiert werden kann, fällt der Builder auf einen Wert von 1 Zentimeter zurück.
Exportieren nach Alembic von Maya
-
Wählen Sie in Maya die Hilfslinien und Group_ID-Kurven aus, die Sie exportieren möchten.
Jeder Knoten braucht einen eindeutigen Namen.
-
Verwenden Sie im Menü Modeling das Menü, um auf die Dropdown-Liste Cache zu klicken, und wählen Sie dann Alembic Cache > Export Selection to Alembic aus.
-
Legen Sie im Fenster Export Selection in der Kategorie General Options die Option Cache time range auf Current Frame fest.
-
Geben Sie in der Kategorie Attributes den Namen des Attribute ein, das Sie in die Liste aufnehmen möchten, und klicken auf die Schaltfläche Add. Fügen Sie die folgenden Schema-Attribute hinzu:
- groom_group_id
- groom_guide
-
Geben Sie einen Dateinamen in das Textfeld File name ein und legen Sie den Files of type auf Alembic fest.
-
Klicken Sie auf die Schaltfläche Export Selection.
Anwenden von Texturen auf Haar-UVs
Die folgenden Schritte und das beigefügte Script helfen Ihnen bei der Einrichtung Ihrer eigenen XGen-Haare, die Sie in Unreal Engine exportieren können, wo Sie Texturen erhalten können, die auf einzelnen Haarsträhnen repräsentiert werden.
-
In Maya verwenden Sie das Menü Modeling und wählen dort Generate > Create Interactive Groom Splines.
-
Sie können Hilfslinien erstellen und die Haare nach Belieben für Ihr Projekt bürsten. Exportieren Sie die Kurven als Alembic Cache, indem Sie Generate > Cache > Create New Cache auswählen.
-
Entfernen Sie Ihre XGen-Haare, indem Sie sie ausblenden oder löschen. Reimportieren Sie dann Ihre exportierten Haarkurven mit Ihrem Quell-Mesh in der Maya-Szene.
-
Abhängig von Ihrer Szene verfügen Sie über Tausende von Spline-Kurven unter einer oberen Kurve, in diesem Beispiel SplineGrp0. Bearbeiten Sie das folgende Python-Script und ersetzen Sie die folgenden Werte mit denen aus Ihrem Projekt:
- export_directory
- hair_file
- curve_top_group
- uv_mesh
Sie können das Script hier unten herunterladen.
from maya import cmds from maya import OpenMaya import os def create_root_uv_attribute(curves_group, mesh_node, uv_set='map1'): ''' Erstellen des Attributs "groom_root_uv" in der Kurvengruppe. ''' # Kurvengruppe prüfen if not cmds.objExists(curves_group): raise RuntimeError('Gruppe nicht gefunden: "{}"'.format(curves_group)) # Kurven in der Gruppe holen curve_shapes = cmds.listRelatives(curves_group, shapes=True, noIntermediate=True) curve_shapes = cmds.ls(curve_shapes, type='nurbsCurve') if not curve_shapes: raise RuntimeError('Ungültige Kurvengruppe. Keine NURBS-Kurven in der Gruppe gefunden.') else: print "Kurven gefunden" print curve_shapes # Kurvestämme holen points = list() for curve_shape in curve_shapes: point = cmds.pointPosition('{}.cv[0]'.format(curve_shape), world=True) points.append(point) # UVs holen values = list() uvs = find_closest_uv_point(points, mesh_node, uv_set=uv_set) for u, v in uvs: values.append([u, v, 0]) #print (str(u) + " , " + str(v) ) # Attribut erstellen name = 'groom_root_uv' cmds.addAttr(curves_group, ln=name, dt='vectorArray') cmds.addAttr(curves_group, ln='{}_AbcGeomScope'.format(name), dt='string') cmds.addAttr(curves_group, ln='{}_AbcType'.format(name), dt='string') cmds.setAttr('{}.{}'.format(curves_group, name), len(values), *values, type='vectorArray') cmds.setAttr('{}.{}_AbcGeomScope'.format(curves_group, name), 'uni', type='string') cmds.setAttr('{}.{}_AbcType'.format(curves_group, name), 'vector2', type='string') return uvs def find_closest_uv_point(points, mesh_node, uv_set='map1'): ''' Mesh-UV-Koordinaten an bestimmten Punkten suchen. ''' # Mesh prüfen if not cmds.objExists(mesh_node): raise RuntimeError('Knoten nicht gefunden: "{}"'.format(mesh_node)) # uv_set prüfen uv_sets = cmds.polyUVSet(mesh_node, q=True, allUVSets=True) if uv_set not in uv_sets: raise RuntimeError('Ungültiges uv_set angegeben: "{}"'.format(uv_set)) # Mesh als dag-path holen selection_list = OpenMaya.MSelectionList() selection_list.add(mesh_node) mesh_dagpath = OpenMaya.MDagPath() selection_list.getDagPath(0, mesh_dagpath) mesh_dagpath.extendToShape() # Mesh-Funktionsatz holen fn_mesh = OpenMaya.MFnMesh(mesh_dagpath) uvs = list() for i in range(len(points)): script_util = OpenMaya.MScriptUtil() script_util.createFromDouble(0.0, 0.0) uv_point = script_util.asFloat2Ptr() point = OpenMaya.MPoint(*points[i]) fn_mesh.getUVAtPoint(point, uv_point, OpenMaya.MSpace.kWorld, uv_set) u = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_point, 0, 0) v = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_point, 0, 1) uvs.append((u, v)) return uvs def abc_export(filepath, node=None, start_frame=1, end_frame=1, data_format='otawa', uv_write=True): job_command = '-frameRange {} {} '.format(start_frame, end_frame) job_command += '-dataFormat {} '.format(data_format) job_command += '-attr groom_root_uv ' if uv_write: job_command += '-uvWrite ' job_command += '-root {} '.format(node) job_command += '-file {} '.format(filepath) cmds.AbcExport(verbose=True, j=job_command) def main(): export_directory = 'D:/Dev/Ref' hair_file = os.path.join(export_directory, 'hair_export.abc') curve_top_group= 'description1|SplineGrp0' uv_mesh='pPlane1' create_root_uv_attribute( curve_top_group , uv_mesh) abc_export(hair_file, curve_top_group) main() -
Führen Sie in Maya das Script mit den geänderten Werten aus, um eine neue Alembic-Datei ('.abc') zu erstellen, die in Unreal Engine importiert werden kann.
-
Erstellen Sie in Unreal Engine ein neues Material mit dem Hair-Schattierungsmodell. Fügen Sie im Material-Diagramm einen Hair Attributes-Ausdruck hinzu und verbinden Sie die Root UV mit dem UV-Input des Textur-Samples.
Das Attribut
groom_root_uvbestimmt pro Haar die zugrundeliegende Mesh-UV, mit der es gekoppelt ist. Dieses Attribut ist optional und wenn nicht anders angegeben, wird automatisch eine Stamm-UV in der Engine mit sphärischem Mapping erstellt. -
Ziehen Sie Ihre importierte Haar-Alembic-Datei aus dem Inhaltsbrowser in das Level und weisen Sie ihr Ihr Haarmaterial zu. Das sollte etwa so aussehen:
Stellen Sie sicher, dass Ihre Alembic-Datei der Haare im Level eine Breite größer als 0 hat.