mayaがwarningを吐いて鬱陶しい時
メッシュデータをimportしただけでこんなワーニングを吐く時
Warning: The mesh object|objectShape contains invalid or unused components. These can be cleaned up using the Mesh Cleanup dialog. #
場合にもよるけれども、指示通りにcleanup実行してもwarnigが出続ける場合がある。
そのケースの1つとして、孤立している頂点があげられます。
孤立しているvertex
本来edgeやfaceを構成しているはずが、どのfaceにも所属せず1点のみで存在している頂点で、
逆に言えば全vertxIDと全faceに所属しているvertxIDを比較してその差分を取れば、
孤立している頂点が割り出せ・・・・はず。
mayaだと大体面に対してエッジ・頂点の数が少なくなると勝手に削除してくれるので滅多に遭遇しないのですが、
その分遭遇すると厄介ですね。
その為サンプルのデータを用意するのも厄介・・・
とりあえずcubeを作ってmaで保存して、無理やり vtxを1つ情報足してみます。
ここを
setAttr -s 8 ".vt[0:7]" -0.5 -0.5 0.5 0.5 -0.5 0.5 -0.5 0.5 0.5 0.5 0.5 0.5
-0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 -0.5 -0.5 0.5 -0.5 -0.5;
こんな感じに
setAttr -s 8 ".vt[0:8]" -0.5 -0.5 0.5 0.5 -0.5 0.5 -0.5 0.5 0.5 0.5 0.5 0.5
-0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 -0.5 -0.5 0.5 -0.5 -0.5 0 0 0;
Q:9個めのvtxはどーこだ?
設計
ざっくりやると
- meshの全てのvtxIdを取得
- meshの全てのfaceを取得し、そこに接続されているvtxIdを取得
- 両者の差分を出す
という感じですね。
vtxIdはまぁ何とかなるとして、faceに所属しているvtxの方がちょっと面倒そうかなと
これを使って
OpenMaya.MItMeshPolygon
https://help.autodesk.com/view/MAYAUL/2022/JPN/?guid=Maya_SDK_py_ref_class_open_maya_1_1_m_it_mesh_polygon_html
getVertices()とか使えそうですね。
zeroArea() これはこれで別の時に使えそう
スクリプト
まずはfaceとそのvtxから・・・
import maya.cmds as cmds
import maya.api.OpenMaya as om
def listIsolateVtx(target):
mesh_dagPath = om.MGlobal.getSelectionListByName(target).getDagPath(0)
shape_Fn = om.MFnMesh(mesh_dagPath)
face_ids = range(0,shape_Fn.numPolygons)
it = om.MItMeshPolygon(mesh_dagPath)
all_faceVtx_ids = []
for index in face_ids:
it.setIndex(index)
connected_vtx = it.getVertices()
print(connected_vtx)
listIsolateVtx("pCube1")
##結果---------------------
[0, 1, 3, 2]
[2, 3, 5, 4]
[4, 5, 7, 6]
[6, 7, 1, 0]
[1, 7, 5, 3]
[6, 0, 2, 4]
6面分取れてますね。
ただ、もちろん重複があるのでこれも処理しておきたいですね。
この時点でvtx[8]が見えてないので、行けそうな気がしてきました。
import maya.cmds as cmds
import maya.api.OpenMaya as om
def listIsolateVtx(target):
mesh_dagPath = om.MGlobal.getSelectionListByName(target).getDagPath(0)
shape_Fn = om.MFnMesh(mesh_dagPath)
face_ids = range(0,shape_Fn.numPolygons)
it = om.MItMeshPolygon(mesh_dagPath)
all_faceVtx_ids = []
for index in face_ids:
it.setIndex(index)
connected_vtx = it.getVertices()
all_faceVtx_ids.extend(list(connected_vtx))
all_faceVtx_ids = list(set(all_faceVtx_ids))
print(all_faceVtx_ids)
次に vtxを直接確認しに行ってリストを作成
import maya.cmds as cmds
import maya.api.OpenMaya as om
def listIsolateVtx(target):
mesh_dagPath = om.MGlobal.getSelectionListByName(target).getDagPath(0)
shape_Fn = om.MFnMesh(mesh_dagPath)
face_ids = range(0,shape_Fn.numPolygons)
it = om.MItMeshPolygon(mesh_dagPath)
all_faceVtx_ids = []
for index in face_ids:
it.setIndex(index)
connected_vtx = it.getVertices()
all_faceVtx_ids.extend(list(connected_vtx))
all_faceVtx_ids = list(set(all_faceVtx_ids))
all_vtx_ids = []
for i in range(0,shape_Fn.numVertices):
all_vtx_ids.append(i)
print(all_vtx_ids)
listIsolateVtx("pCube1")
#結果-------------------
[0, 1, 2, 3, 4, 5, 6, 7, 8]
お、8いますね
じゃぁ最後に比較してみて・・・
import maya.cmds as cmds
import maya.api.OpenMaya as om
def listIsolateVtx(target):
mesh_dagPath = om.MGlobal.getSelectionListByName(target).getDagPath(0)
shape_Fn = om.MFnMesh(mesh_dagPath)
face_ids = range(0,shape_Fn.numPolygons)
it = om.MItMeshPolygon(mesh_dagPath)
all_faceVtx_ids = []
for index in face_ids:
it.setIndex(index)
connected_vtx = it.getVertices()
all_faceVtx_ids.extend(list(connected_vtx))
all_faceVtx_ids = list(set(all_faceVtx_ids))
all_vtx_ids = []
for i in range(0,shape_Fn.numVertices):
all_vtx_ids.append(i)
isolate_vtx_ids = list(set(all_vtx_ids) - set(all_faceVtx_ids))
return isolate_vtx_ids
listIsolateVtx("pCube1")
# Result: [8] #
取れたかな
id取れたのであとは適当に
cmds.select("pCubeShape1.vtx[8]",r = True)
よし、掴めましたね。
これを削除して、保存して、開き直すと
エラーが消えました!
まとめ
- DCCツール行き来したりとか何かの拍子に生まれてしまう様子
- 孤立してる上に、他のvtxと同じ位置にあったら目視は不可能なのでは?
- スキニングの時にこれが存在してると、厄介そう
- ワーニングだけど黄色メッセージで出てこないので気づきにくい
なぜかたまに対処してくれないけどcleanupでも対処できることもあります。