MAYAでは(何らかの事故で)マテリアルのアサインが取れてしまったポリゴンの表示はこのように蛍光グリーンのような色で表示されるわけですが、
フェイスアサインで一部だけマテリアルがないような状態も作ることができます。これは、フェイスとSGのコネクションを切るだけではダメで、そのような場合は代わりにcompInstObjGroups(コンポーネントインスタンスオブジェクトグループ)で設定されているマテリアルが適用されます。なのでそのcompInstObjGroups側のSGとのコネクションも切ってやることでこのような状態を作り出す事ができます。
作れるからといって、偶然できてしまう事があるのかというとそうそうないのでは? と思ってしまうのですが、知人曰くできたことがあるっぽいので、これを判定するプログラムを書いてみます。
注意点
- そもそもコンポーネントインスタンスオブジェクトグループの存在意義について理解仕切れていないので大きな間違いをしている可能性があります。
- コードがかなり力技です。例によってもっとスマートに解決できる気がします。
実際のコード
def is_face_assigned_all(shape):
"""
フェイスアサインの抜けがあって、マテリアル未定義面ができていないか確認する
:param shape: チェックするシェイプ
:type shape: pymel.nodetypes.Shape
:rtype: bool
"""
# compInstObjGroupsからコネクションがSGに伸びていればフェイスアサインに抜けがあってもマテリアルがない面が現れることはない
indices = shape.compInstObjGroups.getArrayIndices()
found = False
for i in indices:
group = shape.compInstObjGroups[i].compObjectGroups[0]
cons = pm.listConnections(group, plugs=True)
if len(cons) > 0 and cons[0].type() == 'shadingEngine':
found = True
break
if found:
return True
# フェイス面ごとにフラグを持ってマテリアルアサイン抜けがある部分を探す
instanceNumber = shape.instanceNumber()
indices = shape.instObjGroups[instanceNumber].objectGroups.getArrayIndices()
numFaces = shape.numFaces()
assined_map = [False] * numFaces
for i in indices:
objectGrpCompList = shape.instObjGroups[instanceNumber].objectGroups[i].objectGrpCompList
faces_list = objectGrpCompList.get() # ex) ['f[0]','f[1:3]']
# 返ってきたフェイス情報が文字列なので力技で面番号のリストに変換する。。。
for faces in faces_list:
faces = faces[2:-1] # ex) '0' or '1:3'
if ':' in faces:
a_ = [int(x) for x in faces.split(':')] # ex [1,3]
a_ = xrange(a_[0], a_[1] + 1) # ex [1,2,3]
else:
a_ = [int(faces)] # ex [0]
# マテリアル設定があった面情報としてTrueをセット
for i in a_:
assined_map[i] = True
#一つもFalseがなかったら全ての面にマテリアルが定義されている
return not (False in assined_map)
文字列をホゲってるあたりが力技です。
動作検証
前回と同じ検証シーン(やっつけ感半端ない)を使います。

shape = pm.PyNode('pCube1|pCubeShape1') # フェイスアサインのないインスタンスシェイプ
print(is_face_assigned_all(shape)) # -> False
shape = pm.PyNode('pCube2|pCubeShape1') # フェイスアサインのあるインスタンスシェイプ
print(is_face_assigned_all(shape)) # -> True
shape = pm.PyNode('pCube3|pCubeShape3') # インスタンスが存在しないフェイスアサインのないシェイプ
print(is_face_assigned_all(shape)) # -> False
shape = pm.PyNode('pCube4|pCubeShape4') # インスタンスが存在しないフェイスアサインのあるシェイプ
print(is_face_assigned_all(shape)) # -> True
shape = pm.PyNode('pCube5|pCubeShape5') # マテリアルが外れてしまったシェイプ
print(is_face_assigned_all(shape)) # -> False
shape = pm.PyNode('pCube6|pCubeShape6') # 一部faceのマテリアルが外れてしまったシェイプ
print(is_face_assigned_all(shape)) # -> False
とりあえず、正しく動いているようです。