(トポロジーによる)ミラー反転を利用しても、頂点が重なっている場合は、ミラー反転が上手く機能しない。
これは、軸対称にある頂点の1つにしかミラー反転が作用しないからである。

ミラーモディファイアを適用したものであれば、頂点インデックスは左右で同じような採番になるので、予め左右対称になっている頂点(インデックス)を紐づけして、外部ファイルに保存しておけば良い。
スクリプト①(紐づけ)
import bpy
import bmesh
import json
import os
bpy.ops.object.mode_set(mode = 'EDIT')
mesh = bpy.context.active_object.data
bm = bmesh.from_edit_mesh(mesh)
bm.verts.ensure_lookup_table()
dict1 = {}
for v1 in bm.verts:
if v1.co.x > 0:
for v2 in bm.verts:
if v1.co.x == -(v2.co.x) and v1.co.y == v2.co.y and v1.co.z == v2.co.z:
if v1.index in dict1:
dict1[v1.index] = dict1[v1.index] + "," + str(v2.index)
else:
dict1[v1.index] = str(v2.index)
dict2 = {}
for k1 in dict1.keys():
list = []
for k2 in dict1.keys():
if dict1[k1] == dict1[k2]:
list.append(k2)
dict2[k1] = dict1[k1].split(",")[list.index(k1)]
current_folder = os.path.dirname(bpy.data.filepath)
path = current_folder + "\\" + "mirror_verts.json"
with open(path, "w") as json_file:
json.dump(dict2, json_file)
スクリプト②(ミラー反転)
import bpy
import bmesh
import json
import os
bpy.ops.object.mode_set(mode = 'EDIT')
mesh = bpy.context.active_object.data
bm = bmesh.from_edit_mesh(mesh)
bm.verts.ensure_lookup_table()
current_folder = os.path.dirname(bpy.data.filepath)
path = current_folder + "\\" + "mirror_verts.json"
dict3 = {}
with open(path) as json_file:
dict3 = json.load(json_file)
print(dict3)
for k, v in dict3.items():
bm.verts[int(v)].co.x = -(bm.verts[int(k)].co.x)
bm.verts[int(v)].co.y = bm.verts[int(k)].co.y
bm.verts[int(v)].co.z = bm.verts[int(k)].co.z
bpy.ops.object.mode_set(mode = 'OBJECT')
bpy.ops.object.mode_set(mode = 'EDIT')
手順
- Workspace を Scripting に変更する
- スクリプト①をコピペする
- 実行する

- 「mirror_verts.json」というファイルが作成されたことを確認する

- シェイプキーを作成する(任意)
- 向かって右(+x)側の頂点を動かす
- スクリプト②をコピペする
- 実行する

- ミラー反転されたことを確認する

所感
- スクリプトには必要最低限のコードしか書いていないので、適宜修正して使ってほしい。
- 個人的に右側(+x)しか動かさないので、左側(-x)を動かす場合には対応していない。モチベがあれば対応させたい。
- 外部ファイルに書き出すのはスマートではないので、シェイプキーの basis を基に紐づけするのが良いかもしれない。モチベがあれば作成したい。