Edge Crease を利用して切り裂いているような場合や、異なるオブジェクトを結合した場合に、重なっている頂点のウェイトを均したいことがある。
均す前

均した後

スクリプト
import bpy
bpy.ops.object.mode_set(mode='OBJECT')
obj = bpy.context.active_object
vertex_groups = obj.vertex_groups
# 選択している頂点を配列に格納する
verts = []
for v in obj.data.vertices:
if v.select and not v.hide:
verts.append(v.index)
print(f"verts: {verts}")
# 選択している頂点のウェイトを正規化する
def normalize_weights():
for v in verts:
groups = obj.data.vertices[v].groups
if groups:
total_weight = sum([g.weight for g in groups])
if total_weight > 0:
for g in groups:
g.weight /= total_weight
vertex_groups[g.group].add([v], g.weight, 'REPLACE')
normalize_weights()
# 辞書を作成する(キーが頂点インデックス、値が頂点グループとウェイト)
verts_weight = {}
for v in verts:
for vg in vertex_groups:
try:
tmpstr = vg.name + ":" + str(vg.weight(v))
key = str(v)
if key in verts_weight.keys():
verts_weight[key] = verts_weight[key] + "," + tmpstr
else:
verts_weight[key] = tmpstr
except RuntimeError:
pass
print(f"verts_weight: {verts_weight}")
# 辞書を作成する(キーが座標、値が同じ座標にある頂点インデックス達)
co_verts = {}
for v1 in verts:
v1_co = obj.data.vertices[v1].co
v1_co_x = round(v1_co.x, 5)
v1_co_y = round(v1_co.y, 5)
v1_co_z = round(v1_co.z, 5)
key = str(v1_co_x) + "," + str(v1_co_y) + "," + str(v1_co_z)
for v2 in verts:
v2_co = obj.data.vertices[v2].co
v2_co_x = round(v2_co.x, 5)
v2_co_y = round(v2_co.y, 5)
v2_co_z = round(v2_co.z, 5)
if v1 != v2:
if v1_co_x == v2_co_x and \
v1_co_y == v2_co_y and \
v1_co_z == v2_co_z:
if key in co_verts.keys():
co_verts[key] = co_verts[key] + "," + str(v2)
else:
co_verts[key] = str(v2)
print(f"co_verts: {co_verts}")
# とにかく頑張る
for value in co_verts.values():
indices = value.split(",")
tempdict = {}
for index in indices:
try:
temparr1 = verts_weight[index].split(",")
for tempele in temparr1:
temparr2 = tempele.split(":")
key = temparr2[0]
value = float(temparr2[1]) / len(indices)
if key in tempdict.keys():
tempdict[key] = tempdict[key] + value
else:
tempdict[key] = value
except KeyError:
pass
print(tempdict)
# ウェイトを設定する
for index in indices:
for key, value in tempdict.items():
vg = obj.vertex_groups[key]
vg.add([int(index)], value, 'REPLACE')
normalize_weights()
bpy.ops.object.mode_set(mode='EDIT')
所感
スクリプトをもっとシンプルに出来る気がする。