Skip to content

Instantly share code, notes, and snippets.

@OptoCloud
Created January 4, 2023 14:45
Show Gist options
  • Save OptoCloud/48df3c84ea1208eba737491fd29a5dd7 to your computer and use it in GitHub Desktop.
Save OptoCloud/48df3c84ea1208eba737491fd29a5dd7 to your computer and use it in GitHub Desktop.
import bpy
import mathutils
def GetMesh(obj_name):
obj = bpy.data.objects.get(obj_name)
if obj is None:
return None
return obj.data
def GetShapeKey(mesh, shape_key_name):
if mesh is None:
return None
if not mesh.shape_keys:
return None
shape_keys = mesh.shape_keys.key_blocks
if shape_key_name not in shape_keys:
return None
return shape_keys[shape_key_name]
def GetVerticesWithMaterial(mesh, material_name):
material_index = None
for i, mat in enumerate(mesh.materials):
if mat.name == material_name:
material_index = i
break
if material_index is None:
return []
vertices = []
uv_layer = mesh.uv_layers.active
for poly in mesh.polygons:
if poly.material_index == material_index:
for loop_index in poly.loop_indices:
vertex_index = mesh.loops[loop_index].vertex_index
uv_coords = uv_layer.data[loop_index].uv
if vertex_index not in vertices:
vertices.append((vertex_index, uv_coords))
return vertices
def ModifyShapeKeyVertices(source_object_name, source_material_name, target_object_name, target_material_name, shape_key_name, uv_distance_threshold):
# Get the source mesh and the target mesh
source_mesh = GetMesh(source_object_name)
if source_mesh is None:
print("Source object not found")
return
target_mesh = GetMesh(target_object_name)
if target_mesh is None:
print("Target object not found")
return
# Get the shape key for the source mesh
shape_key = GetShapeKey(source_mesh, shape_key_name)
if shape_key is None:
print("Shape key not found in source mesh")
return
# Get the vertices of the source mesh that have the source material
source_vertices = GetVerticesWithMaterial(source_mesh, source_material_name)
if len(source_vertices) == 0:
print("No vertices found with source material")
return
# Get the vertices of the target mesh that have the target material
target_vertices = GetVerticesWithMaterial(target_mesh, target_material_name)
if len(target_vertices) == 0:
print("No vertices found with target material")
return
# Create a dictionary mapping UV coordinates of source vertices to vertex indices
source_uv_dict = {(vertex[1][0], vertex[1][1]): vertex[0] for vertex in source_vertices}
# Iterate through the target vertices and find the closest matching vertex in the source mesh
for target_vertex in target_vertices:
target_uv = target_vertex[1]
closest_uv_distance = float("inf")
closest_vertex_index = None
for source_vertex in source_vertices:
source_uv = source_vertex[1]
uv_distance = mathutils.Vector(source_uv - target_uv).length_squared
if uv_distance < closest_uv_distance:
closest_uv_distance = uv_distance
closest_vertex_index = source_vertex[0]
# Modify the shape key value for the closest matching vertex if it is within the threshold distance
if closest_uv_distance < uv_distance_threshold**2 and closest_vertex_index is not None:
shape_key.data[closest_vertex_index].co = target_mesh.vertices[target_vertex[0]].co
ModifyShapeKeyVertices("MeshObjectA", "MaterialA", "MeshObjectB", "MaterialB", "ShapekeyA", 0.0001)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment