Merge branch 'main' into gh-pages
This commit is contained in:
commit
a4be6057a0
40
README.md
40
README.md
@ -129,9 +129,47 @@ Several Python examples are provided for reference and can be found in the **exa
|
|||||||
Note: Examples are grouped in three groups: DNA, DNACalib, and DNAViewer. These names are embedded as prefixes: dna_, dnacalib_, and dna_viewer_.
|
Note: Examples are grouped in three groups: DNA, DNACalib, and DNAViewer. These names are embedded as prefixes: dna_, dnacalib_, and dna_viewer_.
|
||||||
|
|
||||||
## Example DNA files
|
## Example DNA files
|
||||||
[Two demo DNA files](data/dna) are provided for easier testing of this tool. Any DNA generated with [MetaHumanCreator](https://www.unrealengine.com/en-US/metahuman)
|
[Two demo DNA files](data/dna_files) are provided for easier testing of this tool. Any DNA generated with [MetaHumanCreator](https://www.unrealengine.com/en-US/metahuman)
|
||||||
should work.
|
should work.
|
||||||
|
|
||||||
|
The MHC 2023 spring release introduced changes to the rig definition (number of joints increased as well as the number of expressions).
|
||||||
|
In order to accommodate those changes, we added several files to the repository in `/data/mh4` folder: new [gui scene](/data/mh4/gui.ma), updated [assemble script](/data/mh4/additional_assemble_script.py) and example of Ada’s [DNA file](data/mh4/dna_files/Ada.dna).
|
||||||
|
If a user wants to switch and use this new rig version it is necessary to update paths in their scripts:
|
||||||
|
```python
|
||||||
|
GUI = f"{DATA_DIR}/mh4/gui.ma"
|
||||||
|
ADDITIONAL_ASSEMBLE_SCRIPT = f"{DATA_DIR}/mh4/additional_assemble_script.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
In case character DNA is downloaded from [Quixel Bridge](https://quixel.com/bridge) and we are not sure which rig definition is used, it can be checked with following code:
|
||||||
|
```python
|
||||||
|
from dna import (
|
||||||
|
BinaryStreamReader,
|
||||||
|
DataLayer_All,
|
||||||
|
FileStream,
|
||||||
|
Status,
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_dna_reader(dna_file):
|
||||||
|
stream = FileStream(
|
||||||
|
dna_file, FileStream.AccessMode_Read, FileStream.OpenMode_Binary
|
||||||
|
)
|
||||||
|
reader = BinaryStreamReader(stream, DataLayer_All)
|
||||||
|
reader.read()
|
||||||
|
if not Status.isOk():
|
||||||
|
status = Status.get()
|
||||||
|
raise RuntimeError(f"Error loading DNA: {status.message}")
|
||||||
|
return reader
|
||||||
|
|
||||||
|
character_dna = "path_to/character.dna"
|
||||||
|
reader = load_dna_reader(character_dna)
|
||||||
|
if reader.getDBName() == "MH.4":
|
||||||
|
print("Use mh4 folder")
|
||||||
|
elif reader.getDBName() == "DHI":
|
||||||
|
print("Use data folder")
|
||||||
|
else:
|
||||||
|
print("Unsupported rig definition!")
|
||||||
|
```
|
||||||
|
|
||||||
# Notes
|
# Notes
|
||||||
If a user runs examples in Maya 2022, the value for `ROOT_DIR` should be changed and absolute paths must be used,
|
If a user runs examples in Maya 2022, the value for `ROOT_DIR` should be changed and absolute paths must be used,
|
||||||
e.g. `c:/MetaHuman-DNA-Calibration` in Windows or `/home/user/MetaHuman-DNA-Calibration` in Linux. Important: Use `/` (forward slash), Maya uses forward slashes in path.
|
e.g. `c:/MetaHuman-DNA-Calibration` in Windows or `/home/user/MetaHuman-DNA-Calibration` in Linux. Important: Use `/` (forward slash), Maya uses forward slashes in path.
|
||||||
|
File diff suppressed because it is too large
Load Diff
1231
data/mh4/additional_assemble_script.py
Normal file
1231
data/mh4/additional_assemble_script.py
Normal file
File diff suppressed because it is too large
Load Diff
BIN
data/mh4/dna_files/Ada.dna
Normal file
BIN
data/mh4/dna_files/Ada.dna
Normal file
Binary file not shown.
179084
data/mh4/gui.ma
Normal file
179084
data/mh4/gui.ma
Normal file
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,7 @@ sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/libdnacalib.so.6 /usr/
|
|||||||
|
|
||||||
sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/libembeddedRL4.so /usr/lib/embeddedRL4.mll
|
sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/libembeddedRL4.so /usr/lib/embeddedRL4.mll
|
||||||
|
|
||||||
|
sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/MayaUERBFPlugin.mll /usr/lib/MayaUERBFPlugin.mll
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: Change the path `~/MetaHuman-DNA-Calibration` to where `MetaHuman-DNA-Calibration` is located.
|
Note: Change the path `~/MetaHuman-DNA-Calibration` to where `MetaHuman-DNA-Calibration` is located.
|
||||||
@ -59,3 +60,7 @@ Furthermore, [`additional_assemble_script.py`](/data/additional_assemble_script.
|
|||||||
connect controls. The ideal setup looks like this:
|
connect controls. The ideal setup looks like this:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
The MHC 2023 spring release introduced changes to the rig definition (number of joints increased as well as the number of expressions).
|
||||||
|
In order to accommodate those changes, we added several files to the repository in `/data/mh4` folder: new [gui scene](/data/mh4/gui.ma), updated [assemble script](/data/mh4/additional_assemble_script.py) and example of Ada’s [DNA file](data/mh4/dna_files/Ada.dna).
|
||||||
|
Furthermore, in lib folder we added Maya RBF plugin which is used for controlling neck expressions. Neck setup has recently been improved and adding RBF plugin as well as new gui scene to use it, we get better neck deformations.
|
@ -20,7 +20,7 @@ NOTE: If OUTPUT_DIR does not exist, it will be created.
|
|||||||
from os import makedirs
|
from os import makedirs
|
||||||
from os import path as ospath
|
from os import path as ospath
|
||||||
|
|
||||||
# if you use Maya, use absolute path
|
# If you use Maya, use absolute path
|
||||||
ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
|
ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
|
||||||
OUTPUT_DIR = f"{ROOT_DIR}/output"
|
OUTPUT_DIR = f"{ROOT_DIR}/output"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ NOTE: If OUTPUT_DIR does not exist, it will be created.
|
|||||||
from os import makedirs
|
from os import makedirs
|
||||||
from os import path as ospath
|
from os import path as ospath
|
||||||
|
|
||||||
# if you use Maya, use absolute path
|
# If you use Maya, use absolute path
|
||||||
ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
|
ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
|
||||||
OUTPUT_DIR = f"{ROOT_DIR}/output"
|
OUTPUT_DIR = f"{ROOT_DIR}/output"
|
||||||
|
|
||||||
|
@ -53,10 +53,10 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
makedirs(OUTPUT_DIR, exist_ok=True)
|
makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
|
||||||
# this fixes warning when calling this script with headless maya Warning: line 1: Unknown object type: HIKCharacterNode
|
# This fixes warning when calling this script with headless maya Warning: line 1: Unknown object type: HIKCharacterNode
|
||||||
mel.eval(f"HIKCharacterControlsTool;")
|
mel.eval(f"HIKCharacterControlsTool;")
|
||||||
|
|
||||||
# generate workspace.mel
|
# Generate workspace.mel
|
||||||
mel.eval(f'setProject "{OUTPUT_DIR}";')
|
mel.eval(f'setProject "{OUTPUT_DIR}";')
|
||||||
|
|
||||||
config = RigConfig(
|
config = RigConfig(
|
||||||
@ -70,5 +70,5 @@ if __name__ == "__main__":
|
|||||||
# Renames and saves the scene
|
# Renames and saves the scene
|
||||||
cmds.file(rename=f"{OUTPUT_DIR}/{CHARACTER_NAME}.mb")
|
cmds.file(rename=f"{OUTPUT_DIR}/{CHARACTER_NAME}.mb")
|
||||||
cmds.file(save=True)
|
cmds.file(save=True)
|
||||||
# copy dna fila and workspace file alongside generated scene
|
# Copy dna file and workspace file alongside generated scene
|
||||||
copyfile(CHARACTER_DNA, f"{OUTPUT_DIR}/{CHARACTER_NAME}.dna")
|
copyfile(CHARACTER_DNA, f"{OUTPUT_DIR}/{CHARACTER_NAME}.dna")
|
||||||
|
@ -49,8 +49,7 @@ ADD_COLOR_VERTEX = False
|
|||||||
DNA_DIR = f"{DATA_DIR}/dna_files"
|
DNA_DIR = f"{DATA_DIR}/dna_files"
|
||||||
BODY_DIR = f"{DATA_DIR}/body"
|
BODY_DIR = f"{DATA_DIR}/body"
|
||||||
CHARACTER_DNA = f"{DNA_DIR}/{CHARACTER_NAME}.dna"
|
CHARACTER_DNA = f"{DNA_DIR}/{CHARACTER_NAME}.dna"
|
||||||
ANALOG_GUI = f"{DATA_DIR}/analog_gui.ma"
|
|
||||||
GUI = f"{DATA_DIR}/gui.ma"
|
|
||||||
UP_AXIS = "z"
|
UP_AXIS = "z"
|
||||||
if UP_AXIS not in ("z", "y"):
|
if UP_AXIS not in ("z", "y"):
|
||||||
raise ValueError("UP_AXIS can be 'z' or 'y'")
|
raise ValueError("UP_AXIS can be 'z' or 'y'")
|
||||||
@ -182,7 +181,7 @@ def create_head_and_body_scene(mesh_names):
|
|||||||
|
|
||||||
cmds.file(BODY_FILE, options="v=0", type="mayaAscii", i=True)
|
cmds.file(BODY_FILE, options="v=0", type="mayaAscii", i=True)
|
||||||
if UP_AXIS == "y":
|
if UP_AXIS == "y":
|
||||||
cmds.rotate("-90deg", 0, 0, "root")
|
cmds.joint("root", edit=True, orientation=[-90.0, 0.0, 0.0])
|
||||||
for facial_joint, neck_joint in zip(FACIAL_ROOT_JOINTS, NECK_JOINTS):
|
for facial_joint, neck_joint in zip(FACIAL_ROOT_JOINTS, NECK_JOINTS):
|
||||||
cmds.parent(facial_joint, neck_joint)
|
cmds.parent(facial_joint, neck_joint)
|
||||||
|
|
||||||
@ -287,14 +286,14 @@ if __name__ == "__main__":
|
|||||||
# Loads the builtin plugin needed for FBX
|
# Loads the builtin plugin needed for FBX
|
||||||
cmds.loadPlugin("fbxmaya.mll")
|
cmds.loadPlugin("fbxmaya.mll")
|
||||||
|
|
||||||
# this fixes warning when calling this script with headless maya Warning: line 1: Unknown object type: HIKCharacterNode
|
# This fixes warning when calling this script with headless maya Warning: line 1: Unknown object type: HIKCharacterNode
|
||||||
mel.eval(f"HIKCharacterControlsTool;")
|
mel.eval(f"HIKCharacterControlsTool;")
|
||||||
|
|
||||||
# generate workspace.mel
|
# Generate workspace.mel
|
||||||
mel.eval(f'setProject "{OUTPUT_DIR}";')
|
mel.eval(f'setProject "{OUTPUT_DIR}";')
|
||||||
|
|
||||||
# Export FBX for each lod
|
# Export FBX for each lod
|
||||||
|
cmds.upAxis(ax=UP_AXIS)
|
||||||
dna = get_dna()
|
dna = get_dna()
|
||||||
for lod in range(dna.get_lod_count()):
|
for lod in range(dna.get_lod_count()):
|
||||||
export_fbx_for_lod(dna, lod)
|
export_fbx_for_lod(dna, lod)
|
||||||
|
@ -49,7 +49,7 @@ from os import path as ospath
|
|||||||
|
|
||||||
CHARACTER_NAME = "Ada"
|
CHARACTER_NAME = "Ada"
|
||||||
|
|
||||||
# if you use Maya, use absolute path
|
# If you use Maya, use absolute path
|
||||||
ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
|
ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
|
||||||
OUTPUT_DIR = f"{ROOT_DIR}/output"
|
OUTPUT_DIR = f"{ROOT_DIR}/output"
|
||||||
ROOT_LIB_DIR = f"{ROOT_DIR}/lib"
|
ROOT_LIB_DIR = f"{ROOT_DIR}/lib"
|
||||||
@ -142,9 +142,9 @@ def run_joints_command(reader, calibrated):
|
|||||||
rotation = cmds.joint(joint_name, query=True, orientation=True)
|
rotation = cmds.joint(joint_name, query=True, orientation=True)
|
||||||
joint_rotations.append(rotation)
|
joint_rotations.append(rotation)
|
||||||
|
|
||||||
# this is step 5 sub-step a
|
# This is step 5 sub-step a
|
||||||
set_new_joints_translations = SetNeutralJointTranslationsCommand(joint_translations)
|
set_new_joints_translations = SetNeutralJointTranslationsCommand(joint_translations)
|
||||||
# this is step 5 sub-step b
|
# This is step 5 sub-step b
|
||||||
set_new_joints_rotations = SetNeutralJointRotationsCommand(joint_rotations)
|
set_new_joints_rotations = SetNeutralJointRotationsCommand(joint_rotations)
|
||||||
|
|
||||||
# Abstraction to collect all commands into a sequence, and run them with only one invocation
|
# Abstraction to collect all commands into a sequence, and run them with only one invocation
|
||||||
@ -154,7 +154,7 @@ def run_joints_command(reader, calibrated):
|
|||||||
commands.add(set_new_joints_rotations)
|
commands.add(set_new_joints_rotations)
|
||||||
|
|
||||||
commands.run(calibrated)
|
commands.run(calibrated)
|
||||||
# verify that everything went fine
|
# Verify that everything went fine
|
||||||
if not Status.isOk():
|
if not Status.isOk():
|
||||||
status = Status.get()
|
status = Status.get()
|
||||||
raise RuntimeError(f"Error run_joints_command: {status.message}")
|
raise RuntimeError(f"Error run_joints_command: {status.message}")
|
||||||
@ -163,7 +163,7 @@ def run_joints_command(reader, calibrated):
|
|||||||
def run_vertices_command(
|
def run_vertices_command(
|
||||||
calibrated, old_vertices_positions, new_vertices_positions, mesh_index
|
calibrated, old_vertices_positions, new_vertices_positions, mesh_index
|
||||||
):
|
):
|
||||||
# making deltas between old vertices positions and new one
|
# Making deltas between old vertices positions and new one
|
||||||
deltas = []
|
deltas = []
|
||||||
for new_vertex, old_vertex in zip(new_vertices_positions, old_vertices_positions):
|
for new_vertex, old_vertex in zip(new_vertices_positions, old_vertices_positions):
|
||||||
delta = []
|
delta = []
|
||||||
@ -171,7 +171,7 @@ def run_vertices_command(
|
|||||||
delta.append(new - old)
|
delta.append(new - old)
|
||||||
deltas.append(delta)
|
deltas.append(delta)
|
||||||
|
|
||||||
# this is step 5 sub-step c
|
# This is step 5 sub-step c
|
||||||
new_neutral_mesh = SetVertexPositionsCommand(
|
new_neutral_mesh = SetVertexPositionsCommand(
|
||||||
mesh_index, deltas, VectorOperation_Add
|
mesh_index, deltas, VectorOperation_Add
|
||||||
)
|
)
|
||||||
@ -180,7 +180,7 @@ def run_vertices_command(
|
|||||||
commands.add(new_neutral_mesh)
|
commands.add(new_neutral_mesh)
|
||||||
commands.run(calibrated)
|
commands.run(calibrated)
|
||||||
|
|
||||||
# verify that everything went fine
|
# Verify that everything went fine
|
||||||
if not Status.isOk():
|
if not Status.isOk():
|
||||||
status = Status.get()
|
status = Status.get()
|
||||||
raise RuntimeError(f"Error run_vertices_command: {status.message}")
|
raise RuntimeError(f"Error run_vertices_command: {status.message}")
|
||||||
@ -209,7 +209,7 @@ config = RigConfig(
|
|||||||
)
|
)
|
||||||
build_rig(dna=dna, config=config)
|
build_rig(dna=dna, config=config)
|
||||||
|
|
||||||
# this is step 3 sub-step a
|
# This is step 3 sub-step a
|
||||||
current_vertices_positions = {}
|
current_vertices_positions = {}
|
||||||
mesh_indices = []
|
mesh_indices = []
|
||||||
for mesh_index, name in enumerate(dna.meshes.names):
|
for mesh_index, name in enumerate(dna.meshes.names):
|
||||||
@ -217,15 +217,15 @@ for mesh_index, name in enumerate(dna.meshes.names):
|
|||||||
"mesh_index": mesh_index,
|
"mesh_index": mesh_index,
|
||||||
"positions": get_mesh_vertex_positions_from_scene(name),
|
"positions": get_mesh_vertex_positions_from_scene(name),
|
||||||
}
|
}
|
||||||
# loaded data - end of 3rd step
|
# Loaded data - end of 3rd step
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
# modify rig in maya, 4th step
|
# Modify rig in maya, 4th step
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
# propagate changes to dna, 5th step
|
# Propagate changes to dna, 5th step
|
||||||
reader = load_dna_reader(CHARACTER_DNA)
|
reader = load_dna_reader(CHARACTER_DNA)
|
||||||
calibrated = DNACalibDNAReader(reader)
|
calibrated = DNACalibDNAReader(reader)
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ IMPORTANT: You have to setup the environment before running this example. Please
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# this example is intended to be used in Maya
|
# This example is intended to be used in Maya
|
||||||
|
|
||||||
import dna_viewer
|
import dna_viewer
|
||||||
|
|
||||||
|
BIN
lib/Maya2022/linux/MayaUERBFPlugin.mll
Normal file
BIN
lib/Maya2022/linux/MayaUERBFPlugin.mll
Normal file
Binary file not shown.
BIN
lib/Maya2022/windows/MayaUERBFPlugin.mll
Normal file
BIN
lib/Maya2022/windows/MayaUERBFPlugin.mll
Normal file
Binary file not shown.
BIN
lib/Maya2023/linux/MayaUERBFPlugin.mll
Normal file
BIN
lib/Maya2023/linux/MayaUERBFPlugin.mll
Normal file
Binary file not shown.
BIN
lib/Maya2023/windows/MayaUERBFPlugin.mll
Normal file
BIN
lib/Maya2023/windows/MayaUERBFPlugin.mll
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user