Maya Script Python – コンポーネントの取得

今度はAPI2.0ではなく、Mayaコマンドで手っ取り早くメッシュのコンポーネントを取得できないか。
ということをやっておりました。
サイトでメモされている方もいらっしゃるようで、参考に作りました。

import maya.cmds as cmds

def get_ploy_comp(flag = "vtx"):
	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
	
	sel = cmds.ls(sl=1)
	kw = {x:{y:1} for x,y in zip(flags,kwArgs)}
	smKW = dict(zip(flags,sm))
	
	comp = cmds.filterExpand(cmds.polyListComponentConversion(sel,**kw[flag]),sm=smKW[flag],ex=1)
	if comp:
		node = list(set([x.split(".",1)[0] for x in comp]))
	
	return node,comp

コンポーネントを取得する関数です。
使い方はこんなかんじでいかがでしょうか?

node,cmp = get_ploy_comp("face")

print node,cmp

if cmp:
	cmds.select(cmp,r=1)
	cmds.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
	cmds.hilite(node)
	cmds.selectMode(co=1)

選択されているものがコンポーネントでない場合、メッシュに含まれるすべてのコンポーネントが対象となり、
何も選択しないで実行すれば、Noneが返ってきます。
機能としては便利。

 

さて、コードの中身ですが、最初はシンプルに作っていたのです。

def get_ploy_comp_symple(flag = "vtx"):
	node = None
	
	flags = ["vtx","edge","face","uv","vtxFace"]
	if flag not in flags:
		return -1
	
	sel = cmds.ls(sl=1)
	
	if flag == "vtx":
		comp = cmds.filterExpand(cmds.polyListComponentConversion(sel,tv=1),sm=31,ex=1)
	elif flag == "edge":
		comp = cmds.filterExpand(cmds.polyListComponentConversion(sel,te=1),sm=32,ex=1)
	elif flag == "face":
		comp = cmds.filterExpand(cmds.polyListComponentConversion(sel,tf=1),sm=34,ex=1)
	elif flag == "uv":
		comp = cmds.filterExpand(cmds.polyListComponentConversion(sel,tuv=1),sm=35,ex=1)
	elif flag == "vtxFace":
		comp = cmds.filterExpand(cmds.polyListComponentConversion(sel,tvf=1),sm=70,ex=1)
	
	if comp:
		node = list(set([x.split(".",1)[0] for x in comp]))
	
	return node,comp

素直な感じで、条件分岐でコマンドを実行しております。
もっと工夫できないかなぁ、と最初のコードになりました。
コマンドに渡すのには、キーワード引数の形でなく、辞書を渡す事も出来るんですねぇ。
色々やってたら楽しくなってきて、最終的にこうなりました。
読みにくい。

 

素直に書いたほうが何をしているのか良くわかるので、メンテナンスもしやすい。

 

で、更なる活用例。

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

node,cmp = get_ploy_comp("vtx")
vec1 = pm.dt.Vector(cmds.pointPosition(cmp[0],w=1))
vec2 = pm.dt.Vector(cmds.pointPosition(cmp[1],w=1))

print vec1.distanceTo(vec2)

vec1 = om2.MFloatPoint(cmds.pointPosition(cmp[0],w=1))
vec2 = om2.MFloatPoint(cmds.pointPosition(cmp[1],w=1))

print vec1.distanceTo(vec2)

node,cmp = get_ploy_comp("uv")
uv1 = pm.dt.Vector(cmds.polyEditUV(cmp[0],q=1))
uv2 = pm.dt.Vector(cmds.polyEditUV(cmp[1],q=1))

print uv1.distanceTo(uv2)

一つのエッジを選択して実行すると、エッジを構成する2つの頂点の距離が表示されます。
pymelのVentorクラスとAPI2.0のMFloatPointを使ってみました。
最後にUVの距離も出してみました。

 

それはそうと、SubstanceDesignerでノーマルの回転を以前書きましたが、
その画像を散らして、タイリングテクスチャが作ることができないかなぁ、とずっと考えていたのですが、
FX-Mapの中でPixelProcessorを使わないとできないよなぁ、、と諦めておりました。

 

それがなんと、出来ています、、
ノーマルの回転をチュートリアルで公開している方が、やはり公開されております。
どうやら回転の値をグレースケールに変換してFX-Mapで回転した値をPixelProcessorに渡しているようです。
ちゃんと見ていないし、まだ試していないので不確かですが、確かにその方法ならできそうだ。
面白い事考えるなぁ、、
夏にはSubstanceのシェアーサイトが立ち上がるようで、楽しみです。

Maya Script API2.0 – シーン中のノードを取得

さて、早速続きです。

 

前回シーン中のノードを取得するのに、Mayaコマンドを使って取得しました。
それをAPI2.0だけでやるにはどうしたらいいのだろうか?
以前API2.0の記事を書いてから大分立ちますが、未だに情報は少ないです。
AutoDeskももっとAPI2.0の普及に力を入れれば、Mayaは相当な破壊力を持つツールになると思うのになぁ。

 

まぁ、それはさておき、コードです。

import maya.api.OpenMaya as om2

def get_node_om2():
	
	selList = om2.MGlobal.getSelectionListByName("*")
	
	for x in range(selList.length()):
		print "---"
		print selList.getSelectionStrings(x)
		print selList.getDependNode(x).apiTypeStr
		
get_node_om2()

getSelectionListByNameを*(アスタリクス)を使って全部取得し、
その後に条件分岐で欲しい種類のノードに分ければ良いのかな?という感じです。
それをそれぞれの関数セットに入れて使えば、API2.0だけで何でも出来るようになるでしょう、多分。

 

MODO901、MeshFusionユーザーの特典割引が付いている、、
あぁ、やっぱりアップグレードしちゃうかなぁ、、しばらく仕事で使えそうもないのだけど、、

 

Maya2015になってUVの歪み具合がMODOのように視認しやすくなりました。
で、Unfold3Dというプラグインが追加され、ボーナスツールを入れれば、MODOのようにエッジを選択して、
自動でアンラップして、パックしてくれるようになりました。
パックはMODOに比べると、酷いですけど。
2016のスカルプトはMudBoxのエンジンを載せたのでしょうか?
MODO901の進化はどうなのだろう?Mayaの進化に比べるとちょっと見劣りするのかなぁ、、
OpenSubDevに対応して欲しい。

Maya Script API2.0 – アトリビュートの値をセット

久しぶりにMayaの投稿です。

 

その前に、ijiVFXさんからPythonでのゼロ埋めはstringモジュールのzfill関数で一発でできることを教えていただきました。
ijiVFXさん、ありがとうございました。

 

さて、今回のスクリプトを作るきっかけとなったのは、頂点カラーの表示非表示をトグル制御するスクリプトを作ったことがきっかけでした。
Mayaコマンドで作ってみたのですが、膨大な量のジオメトリがあるシーンで、とてつもなく遅かった。
メッシュのアトリビュートをsetAttrで更新しているのがいけないのだろうか。と、API2.0で作ってみました。
今記事を書いていてふと思ったのですが、そもそもMayaってそんな事をしなくても頂点カラーの表示トグルは出来るのでしょうか?
すみません、知りません。

 

ともかく、シーン中のポリゴンメッシュノードを拾い集め、アトリビュートを変更させるスクリプトです。
ついでに、パースビューの描画も、それに合わせてライトのオンオフやテクスチャのオンオフもトグルします。
はじめに見つけたジオメトリのアトリビュートを参考に、それ以外のものを揃える方式です。
使いやすいように、書き換えてください。

import maya.api.OpenMaya as om2
import maya.cmds as cmds

def set_display_color_om2():
	args = [x for x in cmds.ls(s=1,l=1) if cmds.nodeType(x) == "mesh"]
	colorCh = ["Ambient+Diffuse","None"]
	
	selList = om2.MSelectionList()
	[selList.add(x) for x in args]
	
	flag = not cmds.getAttr("{0:}.displayColors".format(args[0]))
	
	for x in range(selList.length()):
		mDg = selList.getDependNode(x)
		if mDg.hasFn(om2.MFn.kMesh):
			dagPath = selList.getDagPath(x)
			node = dagPath.node()
			fn = om2.MFnDependencyNode(mDg)
			#print fn.name()
			attrDC = fn.attribute("displayColors")
			pDC = om2.MPlug(node,attrDC)
			#print pDC.asInt()
			pDC.setInt(flag)
			
			attrDCC = fn.attribute("displayColorChannel")
			pDCC = om2.MPlug(node,attrDCC)
			#print pDCC.asString()
			pDCC.setString(colorCh[flag])
			#print "==="
	panel = [x for x in cmds.getPanel(type="modelPanel") if x=="modelPanel4"]
	if not panel:
		return
	if flag:
		cmds.modelEditor(panel,e=1,dl="none",da="smoothShaded",dtx=0)
	else:
		cmds.modelEditor(panel,e=1,dl="default",da="smoothShaded",dtx=1)

set_display_color_om2()

で喜び勇んで使ってみたのですが、変わらない、、
どうやら時間がかかっていたのは、Viewport2.0の更新が原因だったようです。
なので、Mayaコマンドと比較しても体感できるレベルではなかった。
より多くのジオメトリが存在するのであれば、別かも知れないが、どうやらあまり意味は無かったようです。
でも、API2.0の勉強になった。

 

ただ、見ての通り、ノードの取得はMayaコマンドを使っております。
それが原因だろうか、とそこもAPI2.0で書き換えて見たのですが、やはり変わらなかった。
それについては次回書きます。

 

で、さらに自分のコードに突っ込むならば、Mayaコマンドですでにメッシュノードに限定させる処理をしておきながら、
API2.0でも条件分岐を付けている。意味が無い。

 

でもようやくAPI2.0でアトリビュートを変更させる方法が分かった。
これでメッシュノードから、スキンクラスタを辿る方法が分かれば高速ウェイトエディタが完成する。
うーん、、あまり必要性を感じないなぁ、、アトリビュートを辿ってゆけばスキンクラスタに辿り付けそうだし、
そもそもそんなに負荷の掛かるウェイト作業なら、ペイントだけで済ませてしまうだろう。
まぁ、備忘録的に。

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

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

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