If you're using auto-weighting in blender and you come across a complex mesh where it just isn't working - you probably have flipped normals. Just tab into edit mode and W>flip. If that doesn't work my workaround was to build a much lower resolution mesh with nice clean topology for auto-weighting, then use this script which I quickly cobbled together to proximity copy weights. It will copy all the weights from the source object to the target object, but be warned it will overwrite any existing vertex groups on the target, which you might be using for other non-binding related tasks.
import bpy
from_object=bpy.data.objects['coat_sim']
to_object=bpy.data.objects['coat_wind']
vert_sample=3
def copy_weights(from_object,to_object,copy_from_vert_index_list,copy_to_vert_index):
#copy_from_vert_list is a list of tuples (vert index, weight)
#dict organised by groupindex:weight
from_weights=dict()
#iterate over the from vertices
for (each_copy_vertex_index,each_copy_vertex_weight) in copy_from_vert_index_list:
for each_group in from_object.data.vertices[each_copy_vertex_index].groups:
if each_group.group not in from_weights:
from_weights[each_group.group]=(each_group.weight*each_copy_vertex_weight)
else:
from_weights[each_group.group]+=(each_group.weight*each_copy_vertex_weight)
print(from_weights)
#iterate over the groups in the to vertex
for each_group in to_object.data.vertices[copy_to_vert_index].groups:
if each_group.group in from_weights:
each_group.weight=from_weights[each_group.group]
else:
each_group.weight=0
print('--')
#select the to object
bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active=to_object
to_object.select=True
#delete all vgs
bpy.ops.object.vertex_group_remove(all=True)
#to:from
index_lookup=dict()
#name=[from,to]
index_pairs=dict()
for index,each_group in enumerate(from_object.vertex_groups):
index_pairs[each_group.name]=[index,-1]
to_object.vertex_groups.new(each_group.name)
for index,each_group in enumerate(to_object.vertex_groups):
if each_group.name in index_pairs.keys():
index_pairs[each_group.name][1]=index
for each_pair in index_pairs.values():
if each_pair[1]==-1:
print(from_object.vertex_groups[each_pair[0]].name+' is missing')
else:
index_lookup[each_pair[1]]=each_pair[0]
#add all the vertices in the to object to each group
for active_group_index in range(0,len(to_object.vertex_groups)):
to_object.vertex_groups.active_index=active_group_index
#enter edit mode
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.object.vertex_group_assign(new=False)
bpy.ops.object.editmode_toggle()
#for each point in the from object
for to_vertex_index,to_vertex in enumerate(to_object.data.vertices):
to_vert_pos=to_vertex.co*to_object.matrix_world
distance_lookup=dict()
for from_vertex_index,from_vertex in enumerate(from_object.data.vertices):
from_vert_pos=from_vertex.co*from_object.matrix_world
dist=(to_vert_pos-from_vert_pos).length
distance_lookup[dist]=from_vertex_index
if 0 in distance_lookup:
chosen_from_vert=distance_lookup[0]
#copy the weights from this vertex
copy_weights(from_object,to_object,[(chosen_from_vert,1)],to_vertex_index)
else:
#order by min dist
sorted_distances=sorted(distance_lookup.keys())
samples=[]
sum_weighting=0
for temp in range(0,vert_sample):
this_weighting=1/sorted_distances[temp]
samples.append([distance_lookup[sorted_distances[temp]],this_weighting])
sum_weighting+=this_weighting
for temp in range(0,vert_sample):
samples[temp][1]/=sum_weighting
copy_weights(from_object,to_object,samples,to_vertex_index)
No comments:
Post a Comment