mail@pastecode.io avatar
a year ago
2.6 kB
import maya.cmds as cmds
import math

def get_average_normal(vertices):
    """Calculate the average normal of a list of vertices."""
    avg_normal = [0.0, 0.0, 0.0]

    for vertex in vertices:
        normal = cmds.polyNormalPerVertex(vertex, query=True, xyz=True)
        avg_normal = [a + b for a, b in zip(avg_normal, normal)]

    total_vertices = len(vertices)
    avg_normal = [n / total_vertices for n in avg_normal]
    return avg_normal

def find_closest_vertex(source_vertices, target_vertices):
    """Find the closest vertex in target_vertices for each vertex in source_vertices."""
    closest_vertices = []

    for src_vertex in source_vertices:
        src_pos = cmds.xform(src_vertex, query=True, translation=True, worldSpace=True)
        closest_vertex = None
        min_distance = float('inf')

        for tgt_vertex in target_vertices:
            tgt_pos = cmds.xform(tgt_vertex, query=True, translation=True, worldSpace=True)
            distance = math.sqrt(sum((a - b) ** 2 for a, b in zip(src_pos, tgt_pos)))

            if distance < min_distance:
                min_distance = distance
                closest_vertex = tgt_vertex


    return closest_vertices

def copy_vertex_normals_in_world_space():
    sel = cmds.ls(selection=True, flatten=True)
    if len(sel) < 2:
        cmds.warning("Please select two rows of vertices: source and target.")

    # Divide the selected vertices into source and target rows
    source_vertices = sel[:len(sel) // 2]
    target_vertices = sel[len(sel) // 2:]

    if len(source_vertices) != len(target_vertices):
        cmds.warning("Both source and target rows must have the same number of vertices.")

    # Find the closest vertex in the target row for each vertex in the source row
    closest_vertices = find_closest_vertex(source_vertices, target_vertices)

    # Copy vertex normals from source to target
    for src_vertex, tgt_vertex in zip(source_vertices, closest_vertices):
        source_normal = cmds.polyNormalPerVertex(src_vertex, query=True, xyz=True)
        cmds.polyNormalPerVertex(tgt_vertex, edit=True, normalXYZ=source_normal)

    cmds.select(target_vertices, replace=True)
    cmds.warning("Vertex normals copied from source to target based on proximity in world space.")

# Example usage:
# Select two rows of vertices: first the source row, then the target row.
# Run the script.