左右対称性が崩れたメッシュを修正する

メッシュが左右対称となるように修正したい時がある。メッシュの左右どちらか半分を削除した後にミラーすれば良い。しかし、左右非対称に頂点が動くようなシェイプキーがある場合は、それができない。

ちなみに、左右対称性が崩れる前に、左右対称となっている頂点インデックスを紐づけしておくのが最善であると思われる。その場合は「頂点インデックスによるミラー反転」という記事を参考にすると良い。

以下のスクリプトを実行して修正する。

import bpy
import bmesh

def symmetrize_vertices(LR, margin):
    
    if LR != "left" and LR != "right":
        print('Type "left" or "right".')
        return
    
    if type(margin) != float and type(margin) != int:
        print('Margin value must be a number.')
        return

    def calc_length(v1, v2):
        lx = (v1.co.x + v2.co.x)**2
        ly = (v1.co.y - v2.co.y)**2
        lz = (v1.co.z - v2.co.z)**2
        return (lx + ly + lz)**0.5

    mesh = bpy.context.selected_objects[0].data
    bm = bmesh.from_edit_mesh(mesh)
    bm.verts.ensure_lookup_table()

    verts_L = []
    verts_R = []

    for v in bm.verts:
        if v.hide == False and v.select == True:
            if abs(v.co.x) < margin:
                v.co.x = 0
            elif v.co.x < 0:
                verts_L.append(v)
            elif v.co.x > 0:
                verts_R.append(v)

    for v_L in verts_L:
        for v_R in verts_R:
            length = calc_length(v_L, v_R)
            if length != 0.0 and length < margin:
                if LR == "left":
                    v_L.co.x = v_R.co.x * (-1)
                    v_L.co.y = v_R.co.y
                    v_L.co.z = v_R.co.z
                else:
                    v_R.co.x = v_L.co.x * (-1)
                    v_R.co.y = v_L.co.y
                    v_R.co.z = v_L.co.z

    bpy.ops.object.mode_set(mode = 'OBJECT')
    bpy.ops.object.mode_set(mode = 'EDIT')

symmetrize_vertices("left", 0.2)

手順は以下の通りである。
① Scripting タブを開く。
② New Text を開く。
③ コードをコピペする。
④ パラメータ値を決定する。
⑤ オブジェクトを選択する。
⑥ 修正したい頂点(左右両方)を選択する。
⑦ スクリプトを実行する。

1番目の引数は、+x 側にある頂点を動かしたい時は、”right” に、-x 側にある頂点を動かしたい時は、”left” に設定する。
2番目の引数は、どの程度のずれまで許容するか決めるためのパラメータである。何度か実行して最適な値を見つけると良い。

y 軸に近い頂点の x 座標は、0 となる。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です