Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
2.6 kB
2
Indexable
Never
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

        closest_vertices.append(closest_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.")
        return

    # 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.")
        return

    # 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)[:3]  # Take only the first three elements (X, Y, Z)
        cmds.polyNormalPerVertex(tgt_vertex, edit=True, normalXYZ=source_normal)

    cmds.select(clear=True)
    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.
copy_vertex_normals_in_world_space()