Metapipe/BuildBody.py

399 lines
17 KiB
Python
Raw Permalink Normal View History

2025-01-15 03:07:36 +08:00
#All Rights Belongs to Uzay CALISKAN
#Artstation Marketplace Standart License
import maya.cmds as cmds
import sys
def body_transformation(gender_mesh):
def add_chain_depth_attribute(joints):
for joint in joints:
if not cmds.attributeQuery('chainDepth', node=joint, exists=True):
cmds.addAttr(joint, longName='chainDepth', attributeType='long', defaultValue=0)
cmds.setAttr(joint + '.chainDepth', keyable=True)
def set_chain_depth_value(joints, value):
for joint in joints:
cmds.setAttr(joint + '.chainDepth', value)
# Get all joints in the scene
all_joints = cmds.ls(type="joint")
# Remove joints in the "DHIhead:spine_04" hierarchy (Avoid HEAD)
exclude_joints = cmds.ls("DHIhead:spine_04", dag=True, type="joint")
all_joints = list(set(all_joints) - set(exclude_joints))
add_chain_depth_attribute(all_joints)
# Filter end joints (joints with no child joints)
end_joints = [joint for joint in all_joints if not cmds.listRelatives(joint, children=True, type='joint')]
# Set chainDepth attribute to 0 for all end joints
set_chain_depth_value(all_joints, 100)
set_chain_depth_value(end_joints, 0)
parents1 = []
for joint_name in end_joints:
p_joint = cmds.listRelatives(joint_name, parent=True, type="joint")
if p_joint:
children = cmds.listRelatives(p_joint, children=True, type="joint") or []
if all(cmds.getAttr(child + ".chainDepth") == 0 for child in children):
parents1.append(p_joint[0])
set_chain_depth_value(parents1, 1)
#Chaindepth add Attr Loop
chainDepth = 1
while parents1:
chainDepth += 1
new_parents = []
for joint_name in parents1:
p_joint = cmds.listRelatives(joint_name, parent=True, type="joint")
if p_joint:
children = cmds.listRelatives(p_joint, children=True, type="joint") or []
if all(cmds.getAttr(child + ".chainDepth") < chainDepth for child in children):
new_parents.append(p_joint[0])
if new_parents:
set_chain_depth_value(new_parents, chainDepth)
parents1 = new_parents
else:
break
j_name = []
j_delta_x = []
j_delta_y = []
j_delta_z = []
# DELTA X CALCULATE
for joint_name in end_joints:
mesh_name = gender_mesh
# 1. Get the world-space position of the joint
joint_pos = cmds.xform(joint_name, query=True, worldSpace=True, translation=True)
# 2. Find the nearest vertex named "NVertex" on the mesh to the joint's position
closest_point_node = cmds.createNode("closestPointOnMesh")
cmds.connectAttr(mesh_name + ".worldMesh", closest_point_node + ".inMesh")
cmds.setAttr(closest_point_node + ".inPosition", joint_pos[0], joint_pos[1], joint_pos[2])
nearest_vertex_index = cmds.getAttr(closest_point_node + ".closestVertexIndex")
cmds.delete(closest_point_node)
vertex = mesh_name + ".vtx[{}]".format(nearest_vertex_index)
cmds.select(vertex, replace=True)
# Grow selection
for i in range(1):
# Get the currently selected vertices
vertices = cmds.ls(selection=True, flatten=True)
# Convert the vertices to edges
edges = []
for vertex in vertices:
edges.extend(cmds.polyListComponentConversion(vertex, fromVertex=True, toEdge=True))
# Select the edges
cmds.select(edges)
# Get the currently selected edges
edges = cmds.ls(selection=True, flatten=True)
# Convert the edges to vertices
vertices = []
for edge in edges:
vertices.extend(cmds.polyListComponentConversion(edge, fromEdge=True, toVertex=True))
# Select the vertices
cmds.select(vertices)
vertices = cmds.ls(selection=True, flatten=True)
# Add the vertices to a list
vertex_position_before = []
for vertex in vertices:
position = cmds.pointPosition(vertex, world=True)
vertex_position_before.append(position)
# 3 Set the target blendshape node to a weight of 1
cmds.setAttr("BodyShape.B2", 1)
# 4. Get the new position of NVertex and find the new position
vertex_position_after = []
for vertex in vertices:
position = cmds.pointPosition(vertex, world=True)
vertex_position_after.append(position)
delta_vertex = []
for i in range(len(vertex_position_after)):
sub_delta = []
for j in range(3):
sub_delta.append(vertex_position_after[i][j] - vertex_position_before[i][j])
delta_vertex.append(sub_delta)
average_vertex = [sum(x) / len(x) for x in zip(*delta_vertex)]
# 5. Move the joint with the distance that NVertex moved
delta_x = average_vertex[0]
delta_y = average_vertex[1]
delta_z = average_vertex[2]
if not cmds.attributeQuery("delta_x", node=joint_name, exists=True):
cmds.addAttr(joint_name, ln="delta_x", at="double")
if not cmds.attributeQuery("delta_y", node=joint_name, exists=True):
cmds.addAttr(joint_name, ln="delta_y", at="double")
if not cmds.attributeQuery("delta_z", node=joint_name, exists=True):
cmds.addAttr(joint_name, ln="delta_z", at="double")
cmds.setAttr(joint_name + ".delta_x", delta_x)
cmds.setAttr(joint_name + ".delta_y", delta_y)
cmds.setAttr(joint_name + ".delta_z", delta_z)
# 6 Reset
cmds.setAttr("BodyShape.B2", 0)
j_name.append(joint_name)
j_delta_x.append(delta_x)
j_delta_y.append(delta_y)
j_delta_z.append(delta_z)
#cmds.move(delta_x, delta_y, delta_z, joint_name, relative=True)
for i in range(len(j_name)):
cmds.move(j_delta_x[i], j_delta_y[i], j_delta_z[i], j_name[i], relative=True)
#Fix the body parts
moving_joint = []
target_joint = []
def fix_body(moving_joint, target_joint):
m_pos = cmds.xform(moving_joint, query=True, worldSpace=True, rotatePivot=True)
ta_pos = cmds.xform(target_joint, query=True, worldSpace=True, rotatePivot=True)
child_joints = cmds.listRelatives(moving_joint, c=True, type="joint")
child_positions = []
if child_joints:
for child_joint in child_joints:
child_positions.append(cmds.xform(child_joint, q=True, ws=True, t=True))
# Set the translate and rotate pivot attributes of the "FACIAL_C_LowerLipRotation" joint to match those of "FACIAL_C_MouthUpper"
cmds.xform(moving_joint, translation=ta_pos, rotatePivot=m_pos, worldSpace=True)
if child_joints:
for i, child_joint in enumerate(child_joints):
cmds.xform(child_joint, ws=True, t=child_positions[i])
m_pos = cmds.xform(moving_joint, query=True, worldSpace=True, rotatePivot=True)
ta_pos = cmds.xform(target_joint, query=True, worldSpace=True, rotatePivot=True)
cmds.xform(target_joint, translation=m_pos, rotatePivot=ta_pos, worldSpace=True)
# Filter joints with a chainDepth value of 0
CD = 1
lower_CD = 0
maxCD = 15
while CD <= maxCD:
joint_CD = [joint for joint in all_joints if cmds.getAttr(joint + ".chainDepth") == CD]
lower_joints = [joint for joint in all_joints if cmds.getAttr(joint + ".chainDepth") == lower_CD]
for joint_name in joint_CD:
first_place = cmds.xform(joint_name, q=True, ws=True, translation=True)
child_joints = cmds.listRelatives(joint_name, children=True, type="joint")
average_point = []
if child_joints:
target_points = []
for child_joint in child_joints:
if child_joint in lower_joints:
delta_x = cmds.getAttr(child_joint + '.delta_x')
delta_y = cmds.getAttr(child_joint + '.delta_y')
delta_z = cmds.getAttr(child_joint + '.delta_z')
target_points.append([delta_x, delta_y, delta_z])
if child_joint in end_joints:
delta_x = cmds.getAttr(child_joint + '.delta_x')
delta_y = cmds.getAttr(child_joint + '.delta_y')
delta_z = cmds.getAttr(child_joint + '.delta_z')
#print(cmds.getAttr(child_joint + ".chainDepth"))
target_points.append([delta_x, delta_y, delta_z])
target_points.append([delta_x, delta_y, delta_z])
target_points.append([delta_x, delta_y, delta_z])
target_points.append([delta_x, delta_y, delta_z])
target_points.append([delta_x, delta_y, delta_z])
average_point = [sum(x) / len(x) for x in zip(*target_points)]
if not average_point:
average_point = [0, 0, 0]
avg_x = average_point[0]
avg_y = average_point[1]
avg_z = average_point[2]
cmds.move(avg_x, avg_y, avg_z, joint_name, relative=True)
for child_joint in child_joints:
cmds.move(-avg_x, -avg_y, -avg_z, child_joint, relative=True)
pureJoint = joint_name[:-2]
last_letter = joint_name[-2:]
joint_name_corrective = pureJoint+"_correctiveRoot"+last_letter
joint_name_half = pureJoint+"_half"+last_letter
if joint_name_corrective in all_joints:
fix_body(joint_name, joint_name_corrective)
#print(joint_name + " fixed to the " + joint_name_corrective)
if joint_name_half in all_joints:
fix_body(joint_name, joint_name_half)
#print(joint_name + " fixed to the " + joint_name_half)
end_place = cmds.xform(joint_name, q=True, ws=True, translation=True)
delta_x = end_place[0] - first_place[0]
delta_y = end_place[1] - first_place[1]
delta_z = end_place[2] - first_place[2]
if not cmds.attributeQuery("delta_x", node=joint_name, exists=True):
cmds.addAttr(joint_name, ln="delta_x", at="double")
if not cmds.attributeQuery("delta_y", node=joint_name, exists=True):
cmds.addAttr(joint_name, ln="delta_y", at="double")
if not cmds.attributeQuery("delta_z", node=joint_name, exists=True):
cmds.addAttr(joint_name, ln="delta_z", at="double")
cmds.setAttr(joint_name + ".delta_x", delta_x)
cmds.setAttr(joint_name + ".delta_y", delta_y)
cmds.setAttr(joint_name + ".delta_z", delta_z)
lower_CD += 1
CD += 1
#
#
# Transfer Body original skeleton to the new head Skeleton
CD = 15
lower_CD = -1
minCD = 0
# Define the joint names and namespaces
head_joint = "DHIhead:spine_04"
body_joint = "DHIbody:spine_04"
# Split the joint names into their respective namespaces and joint names
head_namespace, head_joint_name = head_joint.split(":")
body_namespace, body_joint_name = body_joint.split(":")
# Get the list of child joints for the head joint
head_child_joints = cmds.listRelatives(head_joint, children=True, allDescendents=True,type="joint")
body_child_joints = cmds.listRelatives(body_joint, children=True, allDescendents=True, type="joint")
while CD >= minCD:
joint_CD = [joint for joint in body_child_joints if cmds.getAttr(joint + ".chainDepth") == CD]
for joint_name in joint_CD:
body_namespace, body_joint_name = joint_name.split(":")
# Build the joint names for the current joint
head_current_joint = "{}:{}".format(head_namespace, body_joint_name)
body_current_joint = "{}:{}".format(body_namespace, body_joint_name)
if cmds.objExists(head_current_joint):
moving_joint = body_current_joint
target_joint = head_current_joint
def move2target_joint():
lower_lip_rotation_pos = cmds.xform(moving_joint, query=True, worldSpace=True, rotatePivot=True)
jaw_pos = cmds.xform(target_joint, query=True, worldSpace=True, rotatePivot=True)
# Get the child joints
child_joints = cmds.listRelatives(moving_joint, c=True, type="joint")
# Store the initial positions of the child joints
child_positions = []
if child_joints:
for child_joint in child_joints:
child_positions.append(cmds.xform(child_joint, q=True, ws=True, t=True))
# Set the translate and rotate pivot attributes of the "FACIAL_C_LowerLipRotation" joint to match those of "FACIAL_C_MouthUpper"
cmds.xform(moving_joint, translation=jaw_pos, rotatePivot=lower_lip_rotation_pos, worldSpace=True)
if child_joints:
# Move each child joint back to its original position
for i, child_joint in enumerate(child_joints):
cmds.xform(child_joint, ws=True, t=child_positions[i])
move2target_joint()
lower_CD -= 1
CD -= 1
fix_body("DHIbody:spine_04", "DHIhead:spine_04")
def bind_skin(gender_mesh):
# Body
mesh_obj = cmds.ls(gender_mesh)[0]
# Duplicate the mesh
duplicated_mesh_obj = cmds.duplicate(mesh_obj)[0]
new_name = gender_mesh + "_duplicate"
cmds.rename(duplicated_mesh_obj, new_name)
bind_obj = cmds.ls(new_name)[0]
cmds.select([bind_obj, "DHIbody:root"])
# Bind skin to the mesh
skin_cluster = cmds.skinCluster("DHIbody:root", bind_obj)[0]
# Set the skinning method to "classic linear"
cmds.setAttr(skin_cluster + ".skinningMethod", 1)
cmds.select([mesh_obj, bind_obj])
cmds.copySkinWeights(noMirror=True, surfaceAssociation="closestPoint", influenceAssociation=["name", "oneToOne"])
cmds.delete(mesh_obj)
cmds.rename(bind_obj, gender_mesh)
ROOT_DIR = "c:/dna_calibration"
gender=0
gender_mesh = "f_tal_nrw_body_lod0_mesh"
skeleton_file_path = f"{ROOT_DIR}/data/Fem_Body_skeleton.fbx"
def build_body(ROOT_DIR):
#Toggle Gender
if gender == 0:
skeleton_file_path = f"{ROOT_DIR}/data/Fem_Body_skeleton.fbx"
gender_mesh = "f_tal_nrw_body_lod0_mesh"
elif gender == 1:
skeleton_file_path = f"{ROOT_DIR}/data/Ma_Body_skeleton.fbx"
gender_mesh = "m_med_nrw_body_lod0_mesh"
#Rename Selected as B2
selected_object = cmds.ls(selection=True)
cmds.rename(selected_object, "B2")
# Import the FBX file
cmds.file(skeleton_file_path, i=True, type="FBX", ignoreVersion=True, ra=True, mergeNamespacesOnClash=False, options="fbx")
cmds.select("B2", replace=True)
# Define the blendshape node and target shape names
blendshape_node = "BodyShape"
target_shape = "|body_rig|body_grp|body_geometry_grp|body_lod0_grp|"+gender_mesh+"|"+gender_mesh+"Shape"
cmds.blendShape(gender_mesh, automatic=True)
cmds.rename("blendShape1", "BodyShape")
cmds.blendShape(blendshape_node, edit=True, target=[(target_shape, 0.0, "B2", 1.0)])
cmds.setAttr("BodyShape.B2", 0)
#cmds.setAttr("B2" + ".visibility", 0)
cmds.delete('B2')
body_transformation(gender_mesh)
# Duplicate the head mesh
body_mesh = gender_mesh
new_mesh = cmds.duplicate(body_mesh)[0]
# Unlock the translate attributes
cmds.setAttr(new_mesh+'.translateX', lock=False)
cmds.setAttr(new_mesh+'.translateY', lock=False)
cmds.setAttr(new_mesh+'.translateZ', lock=False)
# Translate the duplicated mesh along the X-axis by 75 units
cmds.move(75, 0, 0, new_mesh, relative=True)
# Add the duplicated mesh as a target blend shape to the existing blend shape node
blend_shape_node = "BodyShape"
cmds.blendShape(blend_shape_node, edit=True, target=(body_mesh, 1, new_mesh, 1.0))
# Set the weight of the new_mesh target blend shape to -1
cmds.setAttr("BodyShape."+new_mesh, -1)
cmds.setAttr("BodyShape.B2", 1)
cmds.delete(gender_mesh+"1")
bind_skin(gender_mesh)
#build_body("c:/dna_calibration")