Maya Script Python – コンポーネントの取得2と上を向いているフェースの選択

以前書いたとことある、コンポーネントの取得用の関数を更新します。

import maya.cmds as cmds

def get_ploy_comp(flag = "vtx",*args):
	node = None
	
	flags = ["vtx","edge","face","uv","vtxFace"]
	sm = [31,32,34,35,70]
	kwArgs = ["tv","te","tf","tuv","tvf"]
	
	if flag not in flags:
		return -1
	
	kw = {x:{y:1} for x,y in zip(flags,kwArgs)}
	smKW = dict(zip(flags,sm))
	
	comp = cmds.filterExpand(cmds.polyListComponentConversion(*args,**kw[flag]),sm=smKW[flag],ex=1,fp=1)
	if comp:
		node = list(set([x.split(".",1)[0] for x in comp]))
	
	return node,comp

使い方は上記の関数を登録し(スクリプトエディタで一回実行)

sel = cmds.ls(sl=1)
node,comp = get_ploy_comp("vtx",*sel)
print node,comp

を実行すると、選択されているものがポリゴンメッシュであれば、その要素をプリントします。
フラグとして「vtx」,「edge」,「face」,「uv」,「vtxFace」を与えることで、返ってくるコンポーネントの種類を選べます。
前は、関数内で完結させておりましたが、今回は使いやすいように、引数を設定しました。

 

pymelだと無駄に遅くなってしまうので、コンポーネントの操作の場合はMayaコマンドの方が良いかと思います。
で、それを使った例として、上を向いているフェースを選択するスクリプトです。
動作としては、オブジェクト選択では、単純に上を向いている面を選択します。引数として小数の値を入力することで、
範囲を設定できます。デフォルトが「1.0」で、小さくなると範囲が狭くなり、大きくなると範囲が広くなります。
既にフェースを選択している場合は、選択されているフェース内から上を向いているもののみを残して選択します。

 

まずはMayaコマンド版

import pymel.core as pm
import maya.cmds as cmds
def select_yup_face_cmds(val = 1.0):
	sel = cmds.ls(sl=1)
	node,comp = get_ploy_comp("face",*sel)
	
	if comp:
		yUp = []
		axis = pm.datatypes.Vector(0,1,0)
		cmds.select(cl=1)
		for x in comp:
			xyz = pm.datatypes.Vector(float(z) for z in cmds.polyInfo(x,fn=1)[0].split()[-3:])
			if xyz.angle(axis) < val:
				yUp.append(x)
		if yUp:
			cmds.selectMode(co=1)
			cmds.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
			cmds.select(yUp,r=1)
		else:
			pm.confirmDialog(t=u"Select Yup",m=u"yUpのフェースは見つかりませんでした",b="OK",db="OK",ds="OK")
			return
	else:
		pm.confirmDialog(t=u"Select Yup",m=u"ポリゴンフェース、もしくはポリゴンフェースを持ったノード\nを選択してから実行して下さい",b="OK",db="OK",ds="OK")
		return

使い方は、オブジェクト、もしくはコンポーネント選択で。

select_yup_face_cmds()

範囲指定する場合は

select_yup_face_cmds(0.5)

のような感じです。
次にAPI2.0版

import pymel.core as pm
import maya.cmds as cmds
import maya.api.OpenMaya as om2

def select_yup_face_om2(val = 1.0):
	sel = cmds.ls(sl=1)
	node,comp = get_ploy_comp("face",*sel)
	
	if not comp:
		return
	
	
	yUp = set()
	axis = om2.MVector(0,1,0)

	selList = om2.MGlobal.getActiveSelectionList()

	if not selList:
		return

	selObj = []
	for x in range(selList.length()):
		mDag = selList.getDagPath(x)
		
		if mDag.hasFn(om2.MFn.kMesh):
			selObj.append(om2.MFnMesh(mDag))

	if selObj:
		for s in selObj:
			for i in range(s.numPolygons):
				xyz = s.getPolygonNormal(i)
				if xyz.angle(axis) < val:
					yUp.add("{0:}.f[{1:}]".format(s.fullPathName(),i))
		if yUp:
			comp = list(set(comp) & yUp)
			cmds.selectMode(co=1)
			cmds.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
			cmds.select(comp,r=1)
		else:
			pm.confirmDialog(t=u"Select Yup",m=u"yUpのフェースは見つかりませんでした",b="OK",db="OK",ds="OK")
			return
	else:
		pm.confirmDialog(t=u"Select Yup",m=u"ポリゴンフェース、もしくはポリゴンフェースを持ったノード\nを選択してから実行して下さい",b="OK",db="OK",ds="OK")
		return

使い方は同じく

select_yup_face_om2()

どちらもpymelモジュールを読んでますが、UIに使用しているだけです。
なので、「pm」を「cmds」に変更すればpymelを読む必要はありません。
やはりUIを作るのはpymelの方が簡単なのでpymelを使ってしまいます。
なので、コピペして使っている部分は残ってしまいます。記事を書いていて気が付きました、、
でも、見なおしてみると、Mayaコマンド版ではVectorをpymelのデータ・タイプを使っているので、必要ですね。
こちらもAPI2.0などで置き換えれば、pymelは必要なくなります。
因みにそのVectorを使っているところの値を変更すれば、上面だけでなく他の面でも同様の処理を組むことができます。
汎用化するのであれば、引数として外に出したほうが良いですね。
そうなると関数名も変えなくてはおかしくなる。
そうやって命名規則って狂ってゆくんですよねぇ。

コメントする

post date*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トラックバックする

トラックバック用URL:

アニメーションが親切に解説されております

レンダリング、ライティングの基本が分かります

図版が見やすい美術解剖書です